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

Hi All, I am trying to call from perl script to a function that is defined inside another perl module. That module is an Inline::CPP, and the function I call to is a cpp function. The function gets a pointer to an int and needs to fill it:
int add_nir(int x, int y, int* ref_int )
I am trying to call that function with :
my $test; add_nir(1,4,\$test);
but I get the following error :
Can't locate auto/PM_wed/add_nir.al in @INC (@INC contains: ...
any other fuction (that doesn't receives a pointer) in the cpp part that is called from the perl script is propogated and executed correctly. Can someone please tell me what I did wrong? Thanks, Nir

Replies are listed 'Best First'.
Re^5: Inline CPP
by syphilis (Archbishop) on Jun 01, 2008 at 12:48 UTC
    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
      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