2017-08-26 42 views
5

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

范围较广的问题也许是天气有可能对封闭添加到由newXS(),以及如何创建引用它当C函数被调用的CV这是它注册。 CvPADLIST()似乎是一个完美的地方,但是对于XSubs来说,当设置PERL_IMPLICIT_CONTEXT时使用它似乎是无效的(在perl的pad.c开头注释。是否可以忽略它?)。有其他地方我可以把简历本地数据?

+0

我不知道XS,但你总是可以让XS函数接受一个明确的参数,然后在纯Perl中执行闭包:'''''''''''make make_closure {my $ ctx = new_context(); return sub {xs_func($ ctx,@_)}; }' – melpomene

+0

@melpomene这很有趣,我可以通过'eval'动态生成一个包装器,每个xs函数都可以注册...这是一种可能性。正在看PERL_MAGIC_ext,也许另一种方式... –

回答

3

有一个ANY slot in CV可用于自定义数据和CvXSUBANY(cv)访问。例如:

CvXSUBANY(cv).any_ptr = my_ptr; 

这个槽通常用于存储XS ALIASes索引和用于XS INTERFACEs函数指针。

+0

这似乎是一种可能性,谢谢。 –

2

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

这基本上等同于来自XS/C++透视图的melpomene的注释,但不需要额外的封装器封装。

如果每个进程只有一个上下文存在,那么使用全局变量也是合法的 - 也许是一个必要的罪恶。还可以比较Safely storing static data in XS

我知道没有机制直接将额外数据与xsubs关联。有可能在CV中引入一些魔力,但这听起来不必要的复杂,除非你不能将你的上下文放入Perl对象中。

+0

如果您编写扩展并从包装主Perl解释器调用c/C++代码,显式上下文的方法感觉自然。但是,当使用perl作为嵌入式解释器并将C++用作包装语言时,那么从嵌入式Perl调用的C++函数应驻留在包装C++程序的上下文中。否则,例如同时将多个解释器嵌入到本地函数中会比较繁琐。 –

+0

@KonradEisele嗯,我明白你的观点。在这种情况下,当初始化解释器时,将单个上下文对象加载到Perl包变量中可能有意义吗? – amon

+1

好的,那将是可能的。然而,这只会解决一个特定的问题。我在玩https://github.com/tomaka/luawrapper,希望有一种机制来实现类似的东西。我现在发现了我可以分配的PERL_MAGIC_ext类型的魔法,所以我想我会尝试这个。 –

4

一种可能性是附加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));