----- Original Message -----
From: "ARTHUR GOLDBERG" <a...@cs.nyu.edu>
#!/usr/bin/perl
use warnings;
use lib '/opt/local/lib/perl5/site_perl/5.8.9/';
print "9 + 16 = ", add(9, 16), "\n";
use Inline CPP => <<'END';
int add(int x, int y) {
return x + y;
}
double addDouble( double *x, double *y ) {
return x[0] + y[0];
}
END
Yes - that's the sort of thing I did in my attempts to re-create the error -
and I expected it *would* re-create the error, because, afaik, there's no
listing in any typemaps that tells perl how to deal with the 'double*' type.
But, instead, I find that compilation succeeds (though the addDouble
function is unusable as it hasn't been bound to perl).
I'm puzzled as to why I get a different result - does it make any difference
if you use Inline::C instead of Inline::CPP in the above script ? (It might
be something I've done locally that's causing the different behaviour.)
Anyway, irrespective of the precise way in which the failure occurs, you
can't just specify 'double*' in the argument list - it won't work since perl
doesn't know how to deal with the 'double*' type. Similarly, you won't be
able to specify a 'double*' as the return type. But you *can* return a
'double', since the lib/ExtUtils/typemap *does* tell perl how to deal with
this type.
Assuming you want to pass 2 array references to addDouble, one solution is
to rewrite addDouble as:
###########################
use warnings;
use Inline C => <<'EOC';
double addDouble( AV * x, AV * y ) {
double sum;
SV ** elem;
elem = av_fetch(x, 0, 0);
if(elem != NULL) /* error check, see perlapi */
sum = SvNV(*elem);
elem = av_fetch(y, 0, 0);
if(elem != NULL) /* error check, see perlapi */
sum += SvNV(*elem);
return sum;
}
EOC
@x = (1.23, 2.34, 3.45);
@y = (4.56, 5.67, 6.78);
$ret = addDouble(\...@x, \...@y);
print $ret, "\n";
#############################
Best to use Inline::C where possible. Inline::CPP is currently unmaintained.
If you do use my above code with Inline::CPP instead of Inline::C, I think
you'll find a problem with passing an AV* as an argument - check the rt.cpan
bug reports for Inline::CPP for a fix. Alternatively, pass the arguments as
SV * (and modify the av_fetch call appropriately):
#############################
use warnings;
use Inline C => <<'EOC';
double addDouble( SV * x, SV * y ) {
double sum;
SV ** elem;
elem = av_fetch((AV*)SvRV(x), 0, 0);
if(elem != NULL) /* error check, see perlapi */
sum = SvNV(*elem);
elem = av_fetch((AV*)SvRV(y), 0, 0);
if(elem != NULL) /* error check, see perlapi */
sum += SvNV(*elem);
return sum;
}
EOC
@x = (1.23, 2.34, 3.45);
@y = (4.56, 5.67, 6.78);
$ret = addDouble(\...@x, \...@y);
print $ret, "\n";
#############################
Yet another option is to write a typemap that specifies how to deal with the
'double*' type, and then include it using the the 'TYPEMAPS' Inline Config
option:
use Inline C => Config =>
TYPEMAPS => '/path/my_typemap';
Also, ultimately I think it would be great to modify the Inline CPP's
Makefile.PL so that it selects the right compiler and library on Mac
OS X.
As I said, it's not currently maintained - best thing to do (imo) is to file
a bug report, along with a patch that fixes the issue. That way, if anyone
does ever get to pick up maintainership of the module, they've got a list of
bugs and fixes to start with. And, in the meantime, the solution will be
visible for any interested party who cares to check out the bug reports.
Cheers,
Rob