首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++调用perl代码- eval_sv不向脚本传递参数

C++调用perl代码- eval_sv不向脚本传递参数
EN

Stack Overflow用户
提问于 2012-09-13 09:57:26
回答 2查看 1.2K关注 0票数 7

下面的示例程序将参数推入Perl堆栈,然后调用"eval_sv“。样例perl语句被执行,但我无法检索从C++作为Perl参数传递的变量。请告诉我我在下面的节目中遗漏了什么。

程序的输出

Hello World 测试 100测试完成

这一行不打印$a和$b的值

代码语言:javascript
复制
string three = "print 'Test\n'; my $z = 100; print $a; print $b; print $z;";

这是我的代码:

代码语言:javascript
复制
#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(); 
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-13 11:15:12

我只是猜这里..。

您尝试将一些值传递给您的Perl代码,方法是将它们放到Perl堆栈上,然后期望shift调用从堆栈中检索值。

根据作用域的不同,shift使用@_@ARGV,两者都不能与“堆栈”互换。只有通过进行perl子程序调用,@_才会被堆栈中的元素填充。这是通过在call_sv手册中描述的传呼函数来完成的。

在您的例子中,shift不是从子例程中调用的,所以它试图从@ARGV转移。但是,由于这个数组是空的,您的变量将被设置为undef,这与您获得的输出是一致的。

如果需要传递参数,我建议将Perl代码编写为匿名子路由。也就是说,您可以用eval_pv()定义子例程,然后在设置堆栈后用call_sv()调用它。您的代码中注释掉的部分似乎表明您已经看过这种方法(但是使用了一个命名的子例程)。

或者,您需要通过使用@ARGV将参数替换为get_av,然后对其执行适当的操作,从而将参数提交给get_av。虽然我不确定@ARGV在任何方面是否有魔力。

票数 3
EN

Stack Overflow用户

发布于 2012-09-26 05:35:43

我已经修改了上面发布在问题中的程序,使它能够与@pmakholm的输入一起工作。

代码语言:javascript
复制
#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();

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12403729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档