你尝试使用的 [ANY]
的想法由于多种原因而不起作用。主要是,ANY
可以用于 typemaps 中,以允许相同的 typemap 适用于不同的固定大小数组,但这并不适用于你所拥有的情况。
C 的语法也不是很正确。你不能写成:
int[4] bar() {
static int data[4];
return data;
}
或者:
int bar()[4] {
static int data[4];
return data;
}
在标准C中,你能得到的最接近的是:
int (*bar())[4] {
static int data[4] = {1,2,3,4};
return &data;
}
但这样做其实也不容易解决问题。
然而,可以使用%array_class
来实现简单的解决方案,例如:
%module test
%inline %{
struct foo {
int member;
};
struct foo *bar() {
struct foo *arr = malloc(sizeof(struct foo) * 4);
for (int i = 0; i < 4; ++i)
arr[i].member = i;
return arr;
}
%}
%include <carrays.i>
%array_class(struct foo, fooArray);
这让我可以做到:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> arr = test.fooArray.frompointer(test.bar())
>>> arr
<test.fooArray; proxy of <Swig Object of type 'fooArray *' at 0xb6f332a8> >
>>> arr[0]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33038> >
>>> arr[1]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33380> >
>>> arr[2]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f33398> >
>>> arr[3]
<test.foo; proxy of <Swig Object of type 'struct foo *' at 0xb6f330c8> >
>>>
我们可以更上一层楼(可能),通过在 SWIG 看到
bar()
之前添加以下内容来注入代码以自动将指针转换为数组类型:
%pythonappend bar() %{
# Wrap it automatically
val = fooArray.frompointer(val)
%}
现在你可以像这样使用它:
Python 3.2.3 (default, May 3 2012, 15:54:42)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> test.bar()[1].member
1
>>> arr = test.bar()
>>> arr[3].member
3
在这些例子中,你需要注意内存所有权的问题。目前为止,内存泄漏了。你可以使用%newobject
告诉SWIG,这块内存由Python方面拥有,但是这样会导致内存过早释放(一旦原始返回值不再被引用),因此你需要安排让原始值保留更久时间。一个完整的示例,它将原始指针保存在数组类实例中,以便在数组包装器本身存在时保持引用:
# Wrap it automatically
newval = fooArray.frompointer(val)
newval.ptr_retain = val
val = newval
struct foo {
int member;
};
struct foo *bar() {
struct foo *arr = malloc(sizeof(struct foo) * 4);
for (int i = 0; i < 4; ++i)
arr[i].member = i;
return arr;
}
需要注意的是,该生成的数组类是无限制的,就像在C语言中的struct foo*
一样。这意味着你无法在Python中对其进行迭代-大小是未知的。如果大小确实是固定的,或者你有某种方法来知道大小,那么可以编写一个类型映射,返回一个PyList,以更好地包装它(在我看来)。虽然这需要更多的工作来编写,但在Python方面使接口更加友好。