python数组 swig_SWIG Python的结构数组

I've been searching for a few days trying to figure out how to turn an array of structures into a Python list. I have a function that returns a pointer to the beginning of the array.

struct foo {

int member;

};

struct foo *bar() {

struct foo *t = malloc(sizeof(struct foo) * 4);

... do stuff with the structs ...

return t;

}

After calling the function from Python I get a single structure but trying to access the other elements of the array causes an error:

foo = bar()

print foo[1].member

TypeError: 'foo' object does not support indexing

I've tried using %array_class but to no avail. I've also tried defining the function as returning an array in the SWIG interface file:

extern struct foo [ANY] bar();

The SWIG documentation is pretty thorough but I can't seem to figure this out.

解决方案

The idea you tried with [ANY] won't work for several reasons. Primarily though ANY can be used in typemaps to allow the same typemap to work with varying fixed size arrays, which isn't what you've got there.

The syntax for C isn't quire right there either. You can't write:

int[4] bar() {

static int data[4];

return data;

}

Or:

int bar()[4] {

static int data[4];

return data;

}

In standard C. The closest you can get is:

int (*bar())[4] {

static int data[4] = {1,2,3,4};

return &data;

}

But that's not really any easier to wrap.

However, the simple solution can be made to work using %array_class, for example:

%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

%array_class(struct foo, fooArray);

This lets me do:

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

>

>>> arr[0]

>

>>> arr[1]

>

>>> arr[2]

>

>>> arr[3]

>

>>>

We can go one step better though (possibly) by injecting the code to to covert the pointer to the array type automatically, by adding the following before bar() is seen by SWIG:

%pythonappend bar() %{

# Wrap it automatically

val = fooArray.frompointer(val)

%}

So you can now use it like:

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

You need to be careful about memory ownership. In these examples so far the memory is leaked. You can use %newobject to tell SWIG that the memory is owned by the Python side, but then it will get released too early (as soon as the original return value is no longer referenced) so you would need to arrange to keep the original value around longer. A complete example of that, which saves the original pointer inside the instance of the array class to keep a reference around as long as the array wrapper itself would be:

%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

%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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值