http://www.perlmonks.org?node_id=689679


in reply to Re^5: Inline CPP
in thread Inline CPP

Hi Rob, Thanks for your help! I want to send a reference to array (test) from perl :
my @test; my $reftest = \@test; add_nir(1,4,\$reftest);
and fill that array inside a cpp funcion (add_nir(..)). I followed your previous reply and I am using the perl guts :
int add_nir(int x, int y, AV** perlList ) { *perlList = newAV(); SV* perlItem=newSViv(2); av_push(*perlList, perlItem); ... }
I am using second layer references (pointer to pointer) because first level reference (see the difference in <AV* perlList> at the function declarations ):
int add_nir(int x, int y, AV* perlList )
didn't work. (after I filled the array in add_nir and left the function to it's caller, the array was empty - does the function
newAV()
allocates on the stack or the heap?) As i said the first level reference compiled but the array was empty on returning to the perl :first redirection level
my @test; add_nir(1,4,\@test); int add_nir(int x, int y, AV* perlList ) { perlList = newAV(); SV* perlItem=newSViv(2); av_push(perlList, perlItem); ...}
and the second level redirection couldn't be used : when running a test using my module I got the following error:
Can't locate auto/PM_wed/add_nir.al in @INC .....
What should I do ? Thanks, Nir

Replies are listed 'Best First'.
Re^7: Inline CPP
by syphilis (Archbishop) on Jun 03, 2008 at 02:29 UTC
    The following Inline::CPP script seems to do what you need on perl-5.8.8 (but not on perl-5.10.0):
    use warnings; use Inline CPP => Config => BUILD_NOISY => 1; use Inline CPP => <<'EOC'; void add_nir(int x, int y, AV * perlList) { SV* perlItem=newSViv(2); av_push(perlList, perlItem); } EOC my @test = (1, 2); print "@test\n"; my $reftest = \@test; add_nir(1, 4, $reftest); print "@test\n";
    On perl-5.8.8 that correctly outputs:
    1 2 1 2 2
    and you can see that the "2" was, in fact, pushed onto the array. But, on perl-5.10.0 I get Can't locate auto/main/add_nir.al in @INC ... which is similar to what you are getting. Apparently, one can't supply an AV* arg to an Inline::CPP function on perl-5.10.0, though there's no such problem with perl-5.8.8. I don't know whether this is an Inline::CPP bug or a perl bug - probably Inline::CPP.

    The above script also works fine on perl-5.10.0 as an Inline::C script - do you really need to use Inline::CPP ? (There's a useful example of doing object-oriented inline using Inline::C in 'perldoc Inline::C-Cookbook'. Look for "Soldier".)

    If you really do need Inline::CPP, you're in luck - there's a simple rewrite of the above script that has add_nir() take an SV instead of an AV, and it works fine with Inline::CPP on perl-5.10.0:
    use warnings; use Inline CPP => Config => BUILD_NOISY => 1; use Inline CPP => <<'EOC'; void add_nir(int x, int y, SV * perlList) { SV* perlItem=newSViv(2); av_push((AV*)SvRV(perlList), perlItem); } EOC my @test = (1, 2); print "@test\n"; my $reftest = \@test; add_nir(1, 4, $reftest); print "@test\n";
    At least that works fine for me on perl-5.10.0. Note that the perl code is exactly the same as in the first script. The only difference is in the way the add_nir() function has been constructed.

    Cheers,
    Rob
      Thanks Rob, It helped. I did the option you wrote (with one level referencing) and it worked.
      void add_nir(int x, int y, AV * perlList) { SV* perlItem=newSViv(2); av_push(perlList, perlItem); }
      I understand that I shouldn't have initialized the AV* inside the cpp code, but only outside in the perl code as you did. Thanks again!
        As I mentioned in my previous post, that rendition of add_nir() won't work with perl 5.10. If that's a concern, then just switch to the other rendition provided in that last post of mine.

        In the meantime, I've gone digging into the Inline::CPP source, found the problem, and made out a bug report about the issue (which includes a fix). That bug report and fix can be found at http://rt.cpan.org//Ticket/Display.html?id=36421 . As I've mentioned there, I really don't know whether the fix I've provided is the correct one.

        Cheers,
        Rob