Python / SWIG:输出一个数组

时间:2012-07-26 22:33:37

标签: python return-value swig

我正在尝试从使用SWIG for Python包装的C函数输出值数组。我尝试的方法是使用以下类型映射。

伪代码:

int oldmain() {
float *output = {0,1};
return output;
}

类型映射:

%typemap(out) float* { 
   int i; 
  $result = PyList_New($1_dim0); 
   for (i = 0; i < $1_dim0; i++) { 
 PyObject *o = PyFloat_FromDouble((double) $1[i]); 
 PyList_SetItem($result,i,o); 
 } 
} 

我的代码编译得很好,但是当我运行访问此函数时它会挂起(没有更多的方法来调试它)。

关于我哪里出错的任何建议?

感谢。

2 个答案:

答案 0 :(得分:6)

允许长度变化的最简单方法是添加另一个输出参数,告诉您数组的大小:

%module test

%include <stdint.i>

%typemap(in,numinputs=0,noblock=1) size_t *len  {
  size_t templen;
  $1 = &templen;
}

%typemap(out) float* oldmain {
  int i;
  $result = PyList_New(templen);
  for (i = 0; i < templen; i++) {
    PyObject *o = PyFloat_FromDouble((double)$1[i]);
    PyList_SetItem($result,i,o);
  }
}

%inline %{
float *oldmain(size_t *len) {
  static float output[] = {0.f, 1.f, 2, 3, 4};
  *len = sizeof output/sizeof *output;
  return output;
}
%}

这是从this answer修改为添加size_t *len,可用于在运行时返回数组的长度。类型映射完全隐藏了Python包装器的输出,而是在%typemap(out)中使用它而不是固定大小来控制返回列表的长度。

答案 1 :(得分:5)

这应该让你前进:

/* example.c */

float * oldmain() {
    static float output[] = {0.,1.};
    return output;
}

你在这里返回一个指针,swig不知道它的大小。普通的$ 1_dim0不起作用,所以你必须硬编码或做其他魔术。像这样:

/* example.i */
%module example
%{
 /* Put header files here or function declarations like below */
  extern float * oldmain();
%}

%typemap(out) float* oldmain {
  int i;
  //$1, $1_dim0, $1_dim1
  $result = PyList_New(2);
  for (i = 0; i < 2; i++) {
    PyObject *o = PyFloat_FromDouble((double) $1[i]);
    PyList_SetItem($result,i,o);
  }
}

%include "example.c"

然后在python中你应该得到:

>> import example
>> example.oldmain()
[0.0, 1.0]

添加文字图时,您可能会发现-debug-tmsearch非常方便,即

swig -python -debug-tmsearch example.i

在为float *oldmain寻找合适的“输出”类型地图时,应清楚地表明您的类型地图已被使用。此外,如果您只想访问c全局变量数组,则可以使用varout的typemap而不仅仅是out来执行相同的操作。