我的这个类有int
和int[2]
个成员,我有一个getMember
访问器方法,它接受成员的索引和void*
并填充(在void*
之后使用成员预先分配的空格:
foobar.h中:
class Foobar {
public:
void getMember(int index, void* data) {
switch (index) {
case 0:
*(int *) data = member0;
break;
case 1:
*(int*) data = member1[0];
*((int*) data + 1) = member1[1];
break;
}
}
int member0;
int member1[2];
};
然后我可以写一个SWIG接口:
%{
#include "foobar.h"
%}
%include "foobar.h"
现在,如果我也添加
%include <cpointer.i>
%pointer_functions(int, intp)
然后我可以在Python中执行以下操作:
>>>p = new_intp()
>>>f = Foobar()
>>>f.member0 = 2
>>>f.getMember(0, p)
>>>intp_value(p)
2
问题1.我宣布了void*
,我正在通过intp
但整个过程都有效。为什么?
问题2.假设你向我解释上面是如何工作的,那么我如何为member1做同样的事情?也就是说,我添加了pointer_functions
代码来完成上述工作(神奇地)。然后我需要添加类似的东西以及要传递的指针p1
以便
>>>f.getMember(1, p1)
的作品?
答案 0 :(得分:0)
好吧,我仍然无法回答问题1,但我找到了新的“神奇”方式来回答问题2:
%include <carrays.i>
%array_functions(int, inta);
现在问题1没有改变,问题2变成了,为什么会有效?
答案 1 :(得分:0)
我必须检查SWIG生成的代码,但我的猜测是,对于void *函数参数声明,SWIG不能进行任何类型检查,因此任何给予该函数的类型都将被接受并传递给功能。然后在代码中,将void *转换为int *,只要类型确实是int *,一切都很好。如果你传递的东西不是int *那么你就会得到未定义的行为,例如崩溃,因为你会覆盖一部分对象,或者更糟糕的是,短暂的等等。
所以这应该告诉你,你正在做的事情是相当危险的。我不明白为什么你可以声明你的函数取一个int *因为指针可以引用一个项目或一个数组:
void getMember(int index, int* data) {
switch (index) {
case 0:
*data = member0;
break;
case 1:
*data = member1[0];
*(data + 1) = member1[1];
break;
}
}
然后SWIG将生成代码,该代码将检查传入的类型是否为int *,否则将抛出。我不知道SWIG是否会知道您的inta类型与intp类型兼容。如果没有,你可以使用.i文件中的适配器扩展Foo:
%extend Foobar %{
void getMember(int index, int[2] data) {
getMember(index, data); // C++ knows this is ok
}
}