在嵌入式C应用程序中从Perl调用C函数

14

这是一个非常有趣的问题,可能没有简单的方法来解决,但在决定修改Perl之前,我想先提出我的建议。

所以我有一个调用Perl脚本的C应用程序。它以嵌入式方式工作得很好,我可以传递信息并获得返回信息。然而,现在我的下一个目标是让我的嵌入式脚本能够调用一些在最初调用它的C应用程序中的函数。

这很重要,因为使用XSUB需要将其作为外部库;我不想它成为外部库,我希望直接调用C函数。也许这可以通过XSUB完成,我可能只是读错或者理解错了。

Application -(run)-> Perl

Application <-(function_x())- Perl

Application -(returnfunction_x)-> Perl

这不能成为一个外部库的原因是我依赖于仅在应用程序内创建/存储的数据。


在Python中实现的方法是创建一个C语言的FFI函数,然后将其添加到虚拟模块的字典中,该模块由Python脚本导入。不确定Perl是否以相同的方式完成。 - Ignacio Vazquez-Abrams
1个回答

8

XSUBs实际上不需要外部库。它们仅提供从perl空间调用c函数的能力,并在C和Perl之间映射调用约定时提供一些便利。

您所需做的就是使用您嵌入的perl解释器注册已编译为嵌入式应用程序的XSUBs。

#include "XSUB.h"

XS(XS_some_func);
XS(XS_some_func)
{
    dXSARGS;
    char *str_from_perl, *str_from_c;

    /* get SV*s from the stack usign ST(x) and friends, do stuff to them */
    str_from_perl = SvPV_nolen(ST(0));

    /* do your c thing calling back to your application, or whatever */
    str_from_c = some_c_func(str_from_perl);

    /* pack up the c retval into an sv again and return it on the stack */
    mXPUSHp(c_str);
    XSRETURN(1);
}

/* register the above XSUB with the perl interpreter after creating it */
newXS("Some::Perl::function", XS_some_func, __FILE__);

当嵌入Perl时,通常会在传递给parse_perl的xs_init函数中完成此类操作。

EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);

static void
xs_init (pTHX)
{
    newXS("Some::Perl::function", XS_some_func, __FILE__);
    /* possibly also boot DynaLoader and friends. perlembed has more
     * details on this, and ExtUtils::Embed helps as well. */
    newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}

perl_parse(my_perl, xs_init, argc, my_argv, NULL);

之后,您就可以在perl空间中调用XSUB,如Some::Perl::function,而该XSUB则可以自由地以任何方式回调到您的应用程序。


那么,你粘贴的第一个部分应该放在 .xs 文件中吗? - Suroot
这是C代码,所以我想把它放在一个.c文件中,但我怀疑任何合适的C编译器都不会关心你要求它编译的文件的扩展名 :-) - rafl
1
现在一切都有意义了;我之前认为newXS只是在谈论加载模块。关于perl-xs的文档很少,非常感谢您! - Suroot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接