SWIG Python结构数组
我已经搜索了几天,试图找出如何将结构数组转换为Python列表。我有一个函数,返回指向数组开头的指针SWIG Python结构数组,python,c,swig,Python,C,Swig,我已经搜索了几天,试图找出如何将结构数组转换为Python列表。我有一个函数,返回指向数组开头的指针 struct foo { int member; }; struct foo *bar() { struct foo *t = malloc(sizeof(struct foo) * 4); ... do stuff with the structs ... return t; } 从Python调用函数后,我得到一个结构,但尝试访问数组的其他元素会导致错误:
struct foo {
int member;
};
struct foo *bar() {
struct foo *t = malloc(sizeof(struct foo) * 4);
... do stuff with the structs ...
return t;
}
从Python调用函数后,我得到一个结构,但尝试访问数组的其他元素会导致错误:
foo = bar()
print foo[1].member
TypeError: 'foo' object does not support indexing
我尝试过使用%array\u class
,但没有效果。我还尝试将函数定义为在SWIG接口文件中返回数组:
extern struct foo [ANY] bar();
SWIG文档非常详尽,但我似乎无法理解这一点 您尝试使用的
[ANY]
的想法无法奏效,原因有几个。主要是因为ANY
可以在typemaps中使用,以允许相同的typemap处理不同的固定大小数组,而这不是您所拥有的
这里也不需要C的语法。你不能写:
int[4] bar() {
static int data[4];
return data;
}
或:
在标准C中,最接近的是:
int (*bar())[4] {
static int data[4] = {1,2,3,4};
return &data;
}
但这并不容易包装
但是,可以使用%array\u 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(默认,2012年5月3日,15:54:42)
[GCC 4.6.3]关于linux2
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>导入测试
>>>test.bar()[1]。成员
1.
>>>arr=test.bar()
>>>arr[3]。成员
3.
您需要注意内存所有权。在这些示例中,到目前为止内存是泄漏的。您可以使用%newobject
告诉SWIG内存属于Python端,但这样会过早释放内存(一旦原始返回值不再被引用),因此您需要安排将原始值保留更长时间。这是一个完整的示例,它将原始指针保存在array类的实例中,以便在数组包装器本身存在的时间内保留引用:
%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);
%模块测试
%pythonappend bar()%{
#自动包装
newval=fooArray.frompointer(val)
newval.ptr_retain=val
瓦尔=新瓦尔
%}
%newobjectbar();
%内联%{
结构foo{
国际会员;
};
结构foo*bar(){
struct foo*arr=malloc(sizeof(struct foo)*4);
对于(int i=0;i<4;++i)
arr[i].成员=i;
返回arr;
}
%}
%包括
%数组\类(结构foo,fooArray);
但是请注意,它生成的数组类是无界的,与C中的
struct foo*
非常相似。这意味着在Python中不能对其进行迭代-大小未知。如果大小确实是固定的,或者你有办法知道大小,你可以用一种更好的方式(在我看来)来包装它,方法是写一个返回PyList的typemap。要编写的工作要多一些,但在Python方面会使界面看起来更好。您看过这里吗?-@dpandiar-这是一个完全不同的情况,因为大小是固定的和已知的,数组是成员,而不是从函数返回值。非常感谢!这正是我一直在寻找的,而且工作得非常完美。我从一个计算中知道了数组的大小,为了简化示例,我没有包括这个计算。我看了carrays上的文档。我以前看过,但我被这一点弄糊涂了:“当使用这个宏时,类型被限制为一个简单的类型名,比如int、float或Foo。”我一直尝试使用类型struct Foo*
,当它不起作用时,我认为它只适用于基本的c类型。
%pythonappend bar() %{
# Wrap it automatically
val = fooArray.frompointer(val)
%}
%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);