Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SWIG Python结构数组_Python_C_Swig - Fatal编程技术网

SWIG 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调用函数后,我得到一个结构,但尝试访问数组的其他元素会导致错误:

我已经搜索了几天,试图找出如何将结构数组转换为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);