为什么SWIG允许int指针参数代替void *,以及如何对数组做同样的事情?

时间:2014-01-23 07:23:34

标签: python c++ swig

我的这个类有intint[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)

的作品?

2 个答案:

答案 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
    }
}