I can't get arrayrefs passed into a C function using Inline C. I would like some help, please.
First, just to prove I can get Inline C to work, I'll pass a scalar value to a C function:
#!/usr/bin/perl -I.
#
# try1.pl
#
use Inline C;
my $c = 3.8;
foo( $c );
__END__
__C__
void foo( double c )
{
printf( "C = %f\n", c );
}
And run it:
% ./try1.pl
C = 3.800000
Now do the same thing, but with an arrayref:
#!/usr/bin/perl -I.
#
# try2.pl
#
use Inline C;
my @abc = (1.9, 2.3, 3.8);
foo( \@abc );
__END__
__C__
void foo( double *abc )
{
printf( "C = %f\n", abc[2] );
}
Run it:
% ./try2.pl
Undefined subroutine &main::foo called at ./try1.pl line 7.
Any ideas what I'm doing wrong? Help greatly appreciated!
Inline::C is smart enough to extract values from
SV's based on your C function's type signature. But if you want to pass complex Perl structures to C functions you'll need to use the Perl API to extract the values. So, here's what you need to know for this problem:An array is an instance of a C
structcalledAV. A reference is implemented by astructcalled anRV. All of these are "subtypes" (kinda) of a basestructcalledSV.So to make this function work we need to do a few things.
SV *(pointer to anSV).SVis a reference as opposed to some other kind of scalarRVto get theSVthat it points to.SVis an array, cast it toAVand start working with it.SV.SVwe got from the array is a numerical value suitable for CprintfSV.So putting that all together, we get something like this:
Kinda makes you appreciate how much work Perl does under-the-hood. :)
Now, you don't have to be as super-explicit as that example. You could get rid of some of the temp variables by doing things inline, e.g.
would eliminate the need to declare
num. But I wanted to make it clear how much dereferencing and type-checking is needed to traverse a Perl structure in C.And as @mob points out below, you don't actually have to do all that work (though it's a good idea to be familiar with how it works.)
Inline::C is smart enough that if you declare your function as
It will automatically unwrap the
AVfor you and you can go straight to theav_fetchstep.If all of that seems baffling to you, I highly recommend taking a look at:
perlgutsmanpage, and thenperlapimanpage.