簡體   English   中英

SWIG Python結構數組

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM