C ++调用perl代码 - eval_sv不传递参数到脚本 [英] C++ calling perl code - eval_sv not passing arguments to script

查看:150
本文介绍了C ++调用perl代码 - eval_sv不传递参数到脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有下面的示例程序,将参数推送到Perl堆栈,然后调用eval_sv。示例perl语句被执行,但我不能检索从C ++作为Perl参数传递的变量。请让我知道我在以下程序中丢失了什么



程序输出


Hello World



测试



100测试完成


此行不打印$ a和$ b的值

  string three =print'Test\\\
'; 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)));


/ *完成时带有指向Perl堆栈的指针* /

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 =\
\\\
\
} \\\
\
;

if(perlBeginScript.length()== 0)
{
perlBeginScript =EmbeddedPerl;
}

perlScript =sub;
perlScript + = perlBeginScript;
perlScript + ={\\\
; * /

string one =print'Hello World\\\
';;
string two =my $ a = shift; my $ b = shift;;
string three =print'Test\\\
'; my $ z = 100; print $ a; print $ b; print $ z;;
string four =print'测试complete\\\
';;

perlScript + = one;
perlScript + = two;
perlScript + = three;
perlScript + = four;

// perlScript + = perlEndScript;

/ *使用perl脚本执行* /
my_eval_sv(TRUE);
PL_perl_destruct_level = 1;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}


解决方案

..



您尝试通过将一些值传递给您的Perl代码,将它们放在Perl堆栈,然后您期望 shift c>使用

@_ @ARGV ,两者都不能与堆栈互换。只有使用一个perl子程序调用 @_ ,才会从堆栈中填充元素。这是通过 call_sv nofollow> perlcall manualpage。



在您的情况下, shift ,因此它尝试从 @ARGV 转移。但是由于这个数组是空的,你的变量将被设置为 undef ,这与你得到的输出一致。



如果你需要传递参数,我建议写你的Perl代码作为匿名子路由。这是eval你的子程序定义与 eval_pv()然后调用它与 call_sv()在设置堆栈后。你的代码的注释掉的部分似乎表明你已经看过这种方法(但是有一个命名的子程序)。



或者你需要将你的参数推送到<$通过使用 get_av 退出它,然后对其执行相应的操作,可以使用c $ c> @ARGV 虽然我不知道 @ARGV 是否以任何方式是魔法。


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 shift calls to retrieve values from the stack.

Depending on scope shift uses @_ or @ARGV and neither are interchangeable with "the stack". Only by making a perl subroutine call @_ is populated with elements from the stack. This is done with the call_sv function described in the perlcall manualpage.

In your case shift is not called from inside a subroutine, so it tries to shift from @ARGV. But as this array is empty your variables will be set to undef which 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 with call_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 @ARGV by retireving it with get_avand then perform the appropriate operations on it. Though I am not sure if @ARGVis magic in any way.

这篇关于C ++调用perl代码 - eval_sv不传递参数到脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆