我有下面的示例程序,它将参数推送到Perl堆栈,然后调用" eval_sv"。样本perl语句被执行但我无法检索从C ++传递的变量作为Perl参数。请让我知道以下程序中缺少的内容
该计划的输出
Hello World
测试
100测试完成
此行不会打印$ a和$ b
的值string three = "print 'Test\n'; my $z = 100; print $a; print $b; print $z;";
这是我的代码:
#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();
}
答案 0 :(得分:2)
我只是猜测......
您尝试将某些值传递给Perl代码,方法是将它们放在Perl堆栈上,然后您希望shift
调用从堆栈中检索值。
取决于范围shift
使用@_
或@ARGV
,并且两者都不能与“堆栈”互换。只有通过使用perl子例程调用@_
填充堆栈中的元素。这是通过perlcall手册页中描述的call_sv
功能完成的。
在你的情况下,shift
没有从子程序内部调用,所以它试图从@ARGV
转移。但是,由于此数组为空,因此您的变量将设置为undef
,这与您获得的输出一致。
如果您需要传递参数,我建议您将Perl代码编写为匿名子路由。这是用eval_pv()
评估你的子程序定义,然后在设置堆栈后用call_sv()
调用它。你的代码中注释掉的部分似乎表明你已经看过这种方法(但是使用了一个命名子程序)。
或者,您需要将参数推送到@ARGV
,然后使用get_av
将其退出,然后对其执行相应的操作。虽然我不确定@ARGV
是否有任何魔力。
答案 1 :(得分:0)
我修改了问题中发布的上述程序,使其与@pmakholm的输入一起使用。
#include <EXTERN.h>
#include <perl.h>
#include <string>
#undef do_open
#undef do_close
#include <iostream>
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,c,d,e,f,g,h,i,j,k,l;
a = 900;
b = 1000;
c = 2000;
d = 3000;
e = 4000;
f = 5000;
g = 6000;
h =7000;
i=8000;
k=9000;
l=10000;
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(a)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(b)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(c)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(d)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(e)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(f)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(g)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(h)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(i)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(j)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(k)));
PERL_SET_CONTEXT(my_perl);
XPUSHs(sv_2mortal(newSViv(l)));
/* Done with pushing pointers to Perl stack */
PUTBACK;
SV* sv1 = newSVpv(p, 0);
croak_on_error = eval_sv(sv1, G_EVAL | G_KEEPERR);
cout << "croak on error is" << croak_on_error << endl;
call_pv("Test", G_KEEPERR | G_EVAL);
SPAGAIN;
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 one = "sub Test{print 'Hello World\n'; my $a = shift; my $b = shift; my $c =shift; my $d = shift; my $e = shift; my $f = shift; my $g = shift; my $h = shift; my $i = shift; my $j = shift; my $k=shift; my $l=shift;print $a; print $b; print $c; print $d; print $e; print $f; print $f; print $g; print $h; print $i; print $j; print $k; print $l;} ";
perlScript += one ;
/* 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();
}