您尝试使用的想法[ANY]
因多种原因而行不通。虽然主要ANY
可以在类型映射中使用,以允许相同的类型映射与不同的固定大小的数组一起工作,这不是你所拥有的。
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> >
>>>
不过(可能)通过注入代码来自动转换指向数组类型的指针,我们可以走得更好,通过在bar()
SWIG 看到的之前添加以下内容:
%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 端所有,但它会过早释放(一旦不再引用原始返回值),因此您需要安排将原始值保留更长时间. 一个完整的示例,它将原始指针保存在数组类的实例中,以保持引用,只要数组包装器本身是:
%module test
%pythonappend bar() %{
# Wrap it automatically
newval = fooArray.frompointer(val)
newval.ptr_retain = val
val = newval
%}
%newobject bar();
%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);
Notice though that the array class this generates is unbounded, exactly like a struct foo*
in C. This means you can't iterate over it in Python - the size is unknown. If the size is genuinely fixed, or you have a way of knowing the size somehow you can wrap this in a much nicer (in my view) way by writing a typemap that returns a PyList. It's a bit more work to write, but makes the interface seem nicer on the Python side.