----- 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

Reply via email to