我在C ++程序中有一些嵌入式Perl代码(Ubuntu 14,Perl 5.18,如果这很重要),我在this example中执行Perl。
更具体地说,我:
评估一些“准备”代码:
static const char * redirPre = "$scriptOutput = \"\";\n"
"open(SCRIPTOUTPUT, '> :scalar', \\$scriptOutput) || print STDERR \"Failed to open scriptoutput: $!\";\n"
"print SCRIPTOUTPUT \"huhu\\n\";\n"
"select SCRIPTOUTPUT;\n"
"print SCRIPTOUTPUT \"huhu2\\n\";\n"
"print STDOUT \"huhu2a\\n\";\n";
printf("PRE: '%s'\n", redirPre);
eval_pv(redirPre, FALSE);
评估我的实际Perl片段
现在奇怪的是,如果我静态链接调用所有Perl函数的代码,或者这些函数是在直接链接到主程序的共享库中,这可以很好地工作,而如果这些函数驻留在一个共享的lib,主程序使用dlopen加载。
Perl片段正常执行,只是stdout失败。确切地说,这部分不起作用:
open(SCRIPTOUTPUT, '> :scalar', \$scriptOutput) ||
print STDERR "Failed to open scriptoutput: $!";
无论我是指定>:scalar
还是>
。
有趣的是,输出也没有出现在stdout上,而是显示Failed to open scriptoutput:
(但没有任何实际错误)。
想法?
编辑:使用完全相同的代码将stdout重新路由到/ tmp / xx可以很好地工作,唯一的区别是:
"open(SCRIPTOUTPUT, '>', \"/tmp/xx\") || print STDERR \"Failed: $!\";\n"
答案 0 :(得分:1)
我花了很长时间仔细研究这个问题,最后发现了问题:
最初我使用dlopen("mylib.so", RTLD_LAZY)
加载了我自己的共享库,而lib又是使用libperl.so
的引用构建的。 dlopen手册页指出,当隐式加载依赖库时,标志会向下传播,因此加载libperl也只是RTLD_LAZY。
如上所述重新路由stdout涉及Perl lib scalar.so
,Perl在我的Perl片段执行时加载。 lib scalar.so
包含对PL_no_modify
的未解析引用,该引用再次在libperl.so
中定义。现在,由于我在有效调用RTLD_GLOBAL
时没有指定dlopen(mylib.so)
scalar.so
没有看到PL_no_modify
并且无法加载。
在我的代码中设置RTLD_GLOBAL
之后就可以了。
唯一剩下的问题是为什么Perl没有告诉我......: -