添加了闭包的 Perl newXS()
Perl newXS() with closure added
我想将 Perl 嵌入到 C++ 应用程序中,并且正在寻找一种通过 newXS() 从 Perl 调用 C++ 的方法。除了函数指针之外,我还需要将一个自定义指针关联到由 newXS() 创建的 CV。该指针包含一个 C++ 上下文。我不想为此使用全局变量。有没有一种通用的方法可以做到这一点?
在更广泛的范围内,问题可能是天气有可能 向 newXS() 创建的 CV 添加一个闭包,以及当 c 函数是调用它注册。 CvPADLIST() 似乎是完美的地方,但是对于 XSubs,当设置 PERL_IMPLICIT_CONTEXT 时似乎无效(在 perl 的 pad.c 开头注释)。可以忽略吗?)。有没有其他地方可以放CV本地数据?
最简单(也可能是最好)的方法可能是使上下文显式化——公开面向对象 API 并使用方法而不是函数。当在 Perl 代码中创建 class 的 new
实例时,您将上下文放入该对象中。当您的 XSUB 作为该对象的方法被调用时,它将接收上下文作为第一个参数(即 ST(0)
)。
从 XS/C++ 的角度来看,这基本上等同于 melpomene 的评论,但不需要额外的包装器闭包。
如果每个进程只存在一个上下文,那么使用全局变量也是合法的——也许是一种必要之恶。也比较 Safely storing static data in XS.
我知道没有任何机制可以直接将额外数据与 xsub 相关联。或许可以通过 CV 发挥一些魔力,但这听起来过于复杂,除非您无法将上下文放入 Perl 对象中。
一种可能性是将 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));
有一个 ANY
slot in CV
可用于自定义数据并通过 CvXSUBANY(cv)
访问。例如:
CvXSUBANY(cv).any_ptr = my_ptr;
这个插槽通常用于存储 XS ALIASes and the function pointer for XS INTERFACEs 的索引。
我想将 Perl 嵌入到 C++ 应用程序中,并且正在寻找一种通过 newXS() 从 Perl 调用 C++ 的方法。除了函数指针之外,我还需要将一个自定义指针关联到由 newXS() 创建的 CV。该指针包含一个 C++ 上下文。我不想为此使用全局变量。有没有一种通用的方法可以做到这一点?
在更广泛的范围内,问题可能是天气有可能 向 newXS() 创建的 CV 添加一个闭包,以及当 c 函数是调用它注册。 CvPADLIST() 似乎是完美的地方,但是对于 XSubs,当设置 PERL_IMPLICIT_CONTEXT 时似乎无效(在 perl 的 pad.c 开头注释)。可以忽略吗?)。有没有其他地方可以放CV本地数据?
最简单(也可能是最好)的方法可能是使上下文显式化——公开面向对象 API 并使用方法而不是函数。当在 Perl 代码中创建 class 的 new
实例时,您将上下文放入该对象中。当您的 XSUB 作为该对象的方法被调用时,它将接收上下文作为第一个参数(即 ST(0)
)。
从 XS/C++ 的角度来看,这基本上等同于 melpomene 的评论,但不需要额外的包装器闭包。
如果每个进程只存在一个上下文,那么使用全局变量也是合法的——也许是一种必要之恶。也比较 Safely storing static data in XS.
我知道没有任何机制可以直接将额外数据与 xsub 相关联。或许可以通过 CV 发挥一些魔力,但这听起来过于复杂,除非您无法将上下文放入 Perl 对象中。
一种可能性是将 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));
有一个 ANY
slot in CV
可用于自定义数据并通过 CvXSUBANY(cv)
访问。例如:
CvXSUBANY(cv).any_ptr = my_ptr;
这个插槽通常用于存储 XS ALIASes and the function pointer for XS INTERFACEs 的索引。