I have the below sample program which pushes the arguments to Perl stack and then calls "eval_sv". The sample perl statements get executed but i’m not able to retrieve the variables passed from C++ as Perl arguments. Please let me know what i am missing in the below program
Output of the program
Hello World
Test
100Testing complete
This line doesn’t print the value of $a and $b
string three = "print 'Test\n'; my $z = 100; print $a; print $b; print $z;";
Here is my code:
#include <EXTERN.h>
#include <perl.h>
#include <string>
using namespace std;
string perlScript;
static PerlInterpreter *my_perl;
SV* my_eval_sv(I32 croak_on_error)
{
STRLEN n_a;
char *p1 = new char [perlScript.size()+1];
strcpy(p1, perlScript.c_str());
const char *p = p1;
int len = strlen(p);
dSP;
ENTER ;
SAVETMPS ;
PUSHMARK(SP) ;
int a, b;
a = 10;
b = 20;
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(a)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(b)));
/* Done with pushing pointers to Perl stack */
PUTBACK;
SV* sv1 = newSVpv(p, 0);
eval_sv(sv1, G_EVAL | G_KEEPERR);
SvREFCNT_dec(sv1);
SPAGAIN;
sv1 = POPs;
PUTBACK;
FREETMPS;
LEAVE;
if (croak_on_error && SvTRUE(ERRSV))
croak(SvPVx(ERRSV, n_a));
}
main (int argc, char **argv, char **env)
{
char *embedding[] = { "", "-e", "0" };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, embedding, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
/*string perlBeginScript;
static const char * perlEndScript = "\
\n\
}\n\
";
if(perlBeginScript.length()==0)
{
perlBeginScript="EmbeddedPerl";
}
perlScript = "sub ";
perlScript += perlBeginScript;
perlScript += "{\n"; */
string one = "print 'Hello World\n'; ";
string two = "my $a = shift; my $b = shift; ";
string three= "print 'Test\n'; my $z = 100; print $a; print $b; print $z;";
string four = "print 'Testing complete\n';";
perlScript += one ;
perlScript += two;
perlScript += three;
perlScript += four;
//perlScript += perlEndScript;
/* Done with perl script to be executed */
my_eval_sv(TRUE);
PL_perl_destruct_level = 1;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
I am just guessing here…
You try to pass some values to your Perl code by putting them on the Perl stack and then you expect the
shiftcalls to retrieve values from the stack.Depending on scope
shiftuses@_or@ARGVand neither are interchangeable with “the stack”. Only by making a perl subroutine call@_is populated with elements from the stack. This is done with thecall_svfunction described in the perlcall manualpage.In your case
shiftis not called from inside a subroutine, so it tries to shift from@ARGV. But as this array is empty your variables will be set toundefwhich is consistent with the output you are getting.If you need to pass arguments I would recommend to write your Perl code as a anonymous subrouting. That is eval you subroutine definition with
eval_pv()and then call it withcall_sv()after setting up the stack. The commented out sections of you code seems to indicate that you have looked at this approach (but with a named subroutine).Alternatively you need to push your arguments to
@ARGVby retireving it withget_avand then perform the appropriate operations on it. Though I am not sure if@ARGVis magic in any way.