[英]SWIG Python Structure Array
我一直在尋找幾天試圖找出如何將結構數組轉換為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_class
但無濟於事。 我也嘗試將函數定義為在SWIG接口文件中返回一個數組:
extern struct foo [ANY] bar();
SWIG文檔非常詳盡,但我似乎無法弄清楚這一點。
您嘗試使用[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> >
>>>
盡管(可能)我們可以更好地通過注入代碼來自動轉換指向數組類型的指針,通過在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方擁有的,但是它會過早發布(一旦原始返回值不再被引用),那么您需要安排保留原始值更長的時間。 一個完整的例子,它將原始指針保存在數組類的實例中,以便只要數組包裝器本身保持引用:
%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);
請注意,這個生成的數組類是無界的,就像C中的struct foo*
。這意味着你不能在Python中迭代它 - 大小是未知的。 如果大小是真正修復的,或者你有辦法知道大小,你可以通過編寫一個返回PyList的類型圖以更好的方式(在我的視圖中)包裝它。 這是一個更多的工作,但在Python方面使界面看起來更好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.