7

我想将 Perl 嵌入到 c++ 应用程序中,并且正在寻找一种通过 newXS() 从 perl 调用 c++ 的方法。除了函数指针之外,我还需要将自定义指针关联到由 newXS() 创建的 CV。该指针包含一个 C++ 上下文。我不想为此使用全局变量。有没有一种通用的方法可以做到这一点?

在更广泛的范围内,问题可能是天气有可能向newXS() 创建的 CV 添加一个闭包,以及在调用注册的 c 函数时如何引用它。CvPADLIST () 似乎是一个完美的地方,但是对于 XSubs 来说,当设置 PERL_IMPLICIT_CONTEXT 时使用它似乎是无效的(在 perl 的 pad.c 开头的注释。可以忽略它吗?)。还有其他地方可以放 CV 本地数据吗?

4

3 回答 3

5

一种可能性是将PERL_MAGIC_ext魔法附加到 SV,如 perlguts 中所述:

int  m_free (pTHX_ SV *sv, MAGIC* mg){ ... }
STATIC MGVTBL my_vtbl = { 0, 0, 0, 0, m_free, 0, 0, 0 };
struct ctx;

XS(XS_some_func)
{
    ...
    MAGIC *mg;
    if ((mg = mg_findext((SV*)cv, PERL_MAGIC_ext, &my_vtbl))) {
        ctx *priv = (ctx *)mg->mg_ptr;
    }
    ...
}

并在通过 newXS() 创建 CV 时分配魔法:

   ctx c;
   ...
   CV *cv = newXS(index, XS_some_func, __FILE__);
   MAGIC *mg = sv_magicext((SV *)cv,
                            0,
                            PERL_MAGIC_ext,
                            &my_vtbl,
                            (const char*)&c,
                            sizeof(c));
于 2017-08-26T16:28:04.713 回答
3

有一个ANY插槽CV可用于自定义数据并使用CvXSUBANY(cv). 例如:

CvXSUBANY(cv).any_ptr = my_ptr;

此槽通常用于存储XS ALIAS的索引和XS INTERFACE的函数指针。

于 2017-08-27T13:14:34.907 回答
2

最简单(也可能是最好的)方法可能是使上下文显式化——公开一个面向对象的 API 并使用方法而不是函数。当在 Perl 代码new中创建类的实例时,您将上下文放入该对象中。当您的 XSUB 作为该对象的方法调用时,它将接收上下文作为第一个参数(即ST(0))。

从 XS/C++ 的角度来看,这基本上等同于 melpomene 的评论,但不需要额外的包装闭包。

如果每个进程只存在一个上下文,那么使用全局变量也是合法的——也许是必要的邪恶。也比较安全地在 XS 中存储静态数据

我知道没有将额外数据与 xsub 直接关联的机制。使用 CV 可能会发挥一些魔力,但这听起来不必要地复杂,除非您负担不起将上下文放入 Perl 对象的费用。

于 2017-08-26T15:27:16.767 回答