How can I pass an array from perl to inline C++?

Go To StackoverFlow.com

6

I can't tell if this is a bug or what.

The following code works with Inline::C but not Inline::CPP

#!/usr/bin/perl
use warnings;
use Inline C;

my @array = (1..10);
print findAvLen(\@array), "\n";

__END__
__C__

int findAvLen(AV* arrayIn) {
    return av_len(arrayIn);
}

The above runs fine, but replace C with CPP, and I get the error Can't locate auto/main/findAvLen.al in @INC...

I can get other inline c++ code to work. It is possible, for instance, to pass a list of variables to inline code with an ellipsis as they do in this example, but I wonder why AV* isn't working! For instance, I will want to use a subroutine to converts perl arrays passed to C++ into vectors, e.g. void perl2vector(AV* ar, std::vector<T> &v) {...}, rather than inserting code to perform such conversion into every C++ function I write that takes an array argument. How could I use that example's syntax to pass the perl array to such a converter?


This does seem to be a bug, but in the meantime, uesp has found a workaround:

int findAvLen(SV* arrRef) { 
    AV * arr = MUTABLE_AV(SvRV(arrRef));
    return av_len(arr);
}

arr is now equivalent to the arrayIn desired in the example code above.

2012-04-04 17:24
by flies
Works fine for me: Perl 5.14.0 i686-linux-thread-multi, Inline 0.5, Inline::CPP 0.38. It does seem like a bug that's been fixed, like uesp said, although it seems that all you have to do is upgrade Inline::CPP (not Perl) to version 0.29 or higher - ikegami 2012-04-04 18:20
hrmm, i'm running perl v5.12.3 with Inline::CPP v0.38. I'll try and update the perl and see if that helps - flies 2012-04-04 18:56
I have another box with perl v5.12.4 and I got the same error. Am talking to sysadmin.. - flies 2012-04-04 19:31


4

This appears to be be identical to this Perl bug which exists in 5.10.0 and should have been fixed in release 5.10.29. If you are running 5.10.0-28 try updating. If you aren't running these versions and still getting the error you can try doing what is mentioned in this forum post by changing the AV to SV.

2012-04-04 18:00
by uesp
I'm currently running perl v5.12. - flies 2012-04-04 18:41
Try doing a testing using SV and see if that works for you. If it doesn't, or other trivial test C++ functions results in a similar error, then it is another issue - uesp 2012-04-04 19:10
int f(SV* arrayIn) { return 1; } works, but I'm not sure how I can use SV to access an array (I have used Inline::C before, but never xs, so my experience is limited). Am reading perlguts.. - flies 2012-04-04 19:25
I am blind or illiterate, apparently; you gave the link there... - flies 2012-04-04 19:34
I'll see about fixing the bug, but in the meantime, the forum post linked to above shows that (AV*)SvRV(perlList) converts a SV * (perlList) to a AV *. SvRV is described here http://perldoc.perl.org/perlapi.html#SV-Manipulation-Function - flies 2012-04-04 19:47
@flies, An AV is a type of SV, so all you need is AV * av = MUTABLE_AV(sv);, which is a safer version of AV * av = (AV*)sv;ikegami 2012-04-04 21:48
@ikegami int findAvLen(SV* sv) { return av_len(MUTABLE_AV(sv)); } doesn't seem to work, reports a junk positive integer. av_len(MUTABLE_AV(SvRV(sv))) does work, and if you say it's safer than a plain typecast, I'll be glad to take your word for it. I can't find MUTABLE_AV (nor MUTABLE_SV) in the perlapi or perlguts docs, and the first page of google results doesn't help either - flies 2012-04-05 20:14
following up on prev comment: I'm calling findAvLen like findAvLen(\@a). I understand that SvRV dereferences \@a, and then MUTABLE_AV returns the appropriate type. Incidentally, is there a CONST_AV? (I only need to read and not modify the argument. - flies 2012-04-05 20:21
Oh right, when you say AV, Perl (actually the typemap) dereferences for you. MUTABLE_AV(SvRV(sv)) is indeed required - ikegami 2012-04-05 21:10
@flies, const AV*, you mean? I don't think the typemap will recognize that if you use it as an argument. But you could cast the result of SvRV to a const AV* - ikegami 2012-04-06 11:22
Ads