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
struct
calledAV
. A reference is implemented by astruct
called anRV
. All of these are "subtypes" (kinda) of a basestruct
calledSV
.So to make this function work we need to do a few things.
SV *
(pointer to anSV
).SV
is a reference as opposed to some other kind of scalarRV
to get theSV
that it points to.SV
is an array, cast it toAV
and start working with it.SV
.SV
we got from the array is a numerical value suitable for Cprintf
SV
.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
AV
for you and you can go straight to theav_fetch
step.If all of that seems baffling to you, I highly recommend taking a look at:
perlguts
manpage, and thenperlapi
manpage.