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

It may just be that \$test is not a reference to an int. In any case, I'd be rewriting add_nir(). I think the following does what you want:
use warnings; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'EOC'; void add_nir(int x, int y, SV * ref_int) { sv_setiv(ref_int, x + y); } EOC my $test; add_nir(1, 4, $test); print $test, "\n"; # prints "5"
I also seem to recall that there can be problems when one Inline function tries to access an Inline'd function in a module - but I'm not sure of the details. It's not all that difficult to remove the Inline dependency from a module (thereby making it the same as any other XS module). <plug>InlineX::C2XS and InlineX::CPP2XS can help with that </plug>.

Cheers,
Rob

Replies are listed 'Best First'.
Re^6: Inline CPP
by nirf1 (Novice) on Jun 02, 2008 at 13:04 UTC
    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
      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!