正在寻找从助手函数调用Perl XS C API函数/宏的方法
我一直在试验Perl XS C API,但遇到了一个障碍 我在下面简化了我的例子。假设现有结构MyObject,然后要访问属性“a”或“b”,并为其中一个创建哈希,我可以使用以下代码:正在寻找从助手函数调用Perl XS C API函数/宏的方法,c,perl,xs,C,Perl,Xs,我一直在试验Perl XS C API,但遇到了一个障碍 我在下面简化了我的例子。假设现有结构MyObject,然后要访问属性“a”或“b”,并为其中一个创建哈希,我可以使用以下代码: typedef struct { const char *prop_a; const char *prop_b; struct { const char **items; int num; } names; } MyObjectInfo; typedef MyObje
typedef struct {
const char *prop_a;
const char *prop_b;
struct {
const char **items;
int num;
} names;
} MyObjectInfo;
typedef MyObjectInfo *MyObject;
MODULE = my_obj PACKAGE = MyObject PREFIX = my_obj_
SV *
my_obj_a(o)
MyObject o
CODE:
SV *info = newHV();
hv_store(info, “a”, 1, newSVpvn(o->prop_a, strlen(o->prop_a)), 0);
int i;
for(i = 0; i < o->names.num; i++) {
const char *n = o->names.items[i];
hv_store(info, n, strlen(n), newSViv(i), 0);
}
RETVAL = sv_2mortal(newrv_noinc(val));
OUTPUT:
RETVAL
SV *
my_obj_b(o)
MyObject o
CODE:
SV *info = newHV();
hv_store(info, “b”, 1, newSVpvn(o->prop_b, strlen(o->prop_b)), 0);
int i;
for(i = 0; i < o->names.num; i++) {
const char *n = o->names.items[i];
hv_store(info, n, strlen(n), newSViv(i), 0);
}
RETVAL = sv_2mortal(newrv_noinc(val));
OUTPUT:
RETVAL
事先非常感谢,
Brian首先,您可能缺少以下部分或全部内容:
#定义PERL_NO_GET_上下文
#包括“EXTERN.h”
#包括“perl.h”
#包括“XSUB.h”
主要问题是您没有为API调用提供上下文 一些Perl版本允许进程同时运行多个解释器实例。如果在创建Perl时使用了
-Dmultiplicity
,则构建将支持此功能。(您可以使用perl-V:usemultiplicity
来检查这一点)-Dmultiplicity
由-Dusethreads
表示,该选项用于构建具有线程支持的perl
(因为为每个线程创建了解释器实例)
因此,大量Perl API调用要求调用方提供一个上下文(“THX”),用于标识要使用的解释器。将解释器视为一个对象(在面向对象的意义上),将上下文视为invocant
在XS代码中,会自动为您创建一个包含上下文的变量。该变量通过使用宏自动传递给Perl API调用
#定义新闻vpvn(a,b)Perl_新闻vpvn(aTHX#a,b)
// ^^^^^
//导致传递上下文
//对于Perl_newsvn,实名
//关于新闻VPVN。
因此,您需要上下文来完成这项工作(无论您使用的是newsvvn
还是Perl\u newsvvn
)。要获取上下文,请使用以下宏:
- 如果函数除了上下文之外没有参数,
- 使用
作为函数声明的第一个参数pTHX
- 使用
作为函数调用的第一个参数aTHX
- 使用
- 如果函数除了上下文之外还有参数,
- 使用
作为函数声明的第一个参数pTHX\ux
- 使用
作为函数调用的第一个参数aTHX
- 使用
p
”代表“参数”;“a
”代表“参数”;“”代表逗号
在你的情况下,你会使用
STATIC SV*create\u obj\u hash(pTHX\umyObjectInfo*o、const char*k、const char*p){
#定义create_obj_hash(a,b,c)create_obj_hash(aTHX_a,b,c)
...
}
由于有了#define
,您可以继续使用
SV*info=create_obj_hash(o,“b”,o->prop_b);
未经测试。如果有任何问题,请告诉我。这是否回答了您的问题?特别地,我应该帮助你。谢谢@nwellnhof,这正是我需要的技巧/提示。添加了pTHX和aTHX宏包含使其工作正常。谢谢,所有的标题都在那里-整个事情的关键(正如您所解释的)是缺少aTHX和pTHX宏包含。一旦我加上这些,一切都起作用了。
SV *create_obj_hash(MyObjectInfo *o, const char *k, const char *p) {
SV *val = newHV();
hv_store(val, k, strlen(k), newSVpvn(p, strlen(p)), 0);
int i;
for(i = 0; i < o->names.num; i++) {
const char *n = o->names.items[i];
hv_store(info, n, strlen(n), newSViv(i), 0);
}
return val;
}
MODULE = my_obj PACKAGE = MyObject PREFIX = my_obj_
SV *
my_obj_a(o)
MyObject o
CODE:
SV *info = create_obj_hash(o, “a”, o->prop_a);
RETVAL = sv_2mortal(newrv_noinc(val));
OUTPUT:
RETVAL
SV *
my_obj_b(o)
MyObject o
CODE:
SV *info = create_obj_hash(o, “b”, o->prop_b);;
RETVAL = sv_2mortal(newrv_noinc(val));
OUTPUT:
RETVAL
myobj.xs: In function 'create_obj_hash':
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/perl.h:175:16: error: 'my_perl' undeclared (first use in this function); did you mean 'my_fork'?
# define aTHX my_perl
^~~~~~~
ppport.h:6145:41: note: in definition of macro 'MUTABLE_PTR'
# define MUTABLE_PTR(p) ({ void *_p = (p); _p; })
^
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/hv.h:651:17: note: in expansion of macro 'MUTABLE_HV'
#define newHV() MUTABLE_HV(newSV_type(SVt_PVHV))
^~~~~~~~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/perl.h:188:18: note: in expansion of macro 'aTHX'
# define aTHX_ aTHX,
^~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/embed.h:532:40: note: in expansion of macro 'aTHX_'
#define newSV_type(a) Perl_newSV_type(aTHX_ a)
^~~~~
/usr/lib/x86_64-linux-gnu/perl/5.28/CORE/hv.h:651:28: note: in expansion of macro 'newSV_type'
#define newHV() MUTABLE_HV(newSV_type(SVt_PVHV))
^~~~~~~~~~
myobj.xs:42:19: note: in expansion of macro 'newHV'
return (void*)newHV();