Here's an Inline::C demo that does pretty much the same thing, but bypasses the creation of a couple of extra SV's:
use strict;
use warnings;
use Inline C => Config =>
CLEAN_AFTER_BUILD => 0,
BUILD_NOISY => 1;
use Inline C => <<'EOC';
double wrap_cos(SV * in) {
if(sv_isobject(in)) {
HV *self_hv = MUTABLE_HV(SvRV(in));
SV **callback_ptr = hv_fetchs(self_hv, "Number", 0);
return cos(SvNV(*callback_ptr));
}
return cos(SvNV(in));
}
EOC
my $angle = 0.5;
my $x = {'Number' => $angle};
bless $x;
print wrap_cos($x), "\n"; # Output: 0.877582561890373
print wrap_cos($angle), "\n"; # Output: 0.877582561890373
Inline::C is just XS under the hood, and the XS file that it autogenerates and compiles (and can be found under ./_Inline/build) is:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "INLINE.h"
double wrap_cos(SV * in) {
if(sv_isobject(in)) {
HV *self_hv = MUTABLE_HV(SvRV(in));
SV **callback_ptr = hv_fetchs(self_hv, "Number", 0);
return cos(SvNV(*callback_ptr));
}
return cos(SvNV(in));
}
MODULE = try_pl_96f2 PACKAGE = main
PROTOTYPES: DISABLE
double
wrap_cos (in)
SV * in
Maybe there's something there that helps you ... or maybe not ;-)
(The header file INLINE.h is generally not necessary, and is not needed here. You'll find it in the same folder as the XS file.)
Cheers,
Rob