Swig,返回一系列双打

我知道,通常有很多方法可以解决某些问题。 但在这里,我知道我希望它采用哪种方式,但我无法使其与Python和SWIG一起使用…

我有一个C函数,它返回一个double值数组:

double *my(int x) { double a,b,*buf; buf = malloc (x * sizeof(double)); a=3.14; b=2.7; buf[0]=a; buf[1]=b; return buf; } 

在这里,我明确地希望将数组作为返回值。 不像在许多示例中那样写入输入数组的’void’函数。 现在,我想获得一个SWIG-python包装器,它可以用作:

 >>> import example >>> print example.my(7) [3.14,2.7] 

无论我做什么,我都有一些概念上的问题 – 我总是得到s.th. 喜欢

我试图在swg文件中定义一些类型图:

 %typemap(out) double [ANY] { 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); } } 

但我仍然无法按要求取出我的结果。 有没有人有一个简单的代码示例来实现这个任务?

第一个问题是你的typemap不匹配,你需要一个%typemap(out) double * { ... }因为你的函数返回一个指向double而不是double数组的指针。

如果您的列表具有固定大小(即整数字面),如您给出的示例(我假设不是您想要的),您可以简单地更改我在上面给出的类型$1_dim0 ,并将$1_dim0为固定大小。

否则你的问题是你的%typemap(out) double *不可能知道你的参数int x的值。 您可以返回一个包含指针和大小的结构。 然后你可以很容易地定义一个类型映射,把它变成一个列表(或者一个NumPy数组,另见我对Wrap C结构的响应,数组成员可以在python中访问:SWIG?cython?ctypes? )。

顺便说一下,不可能在C中返回一个固定大小的数组(另见答案: 声明一个C函数返回一个数组 ),因此%typemap(out) double [ANY] { ... }永远不会匹配。

我遇到了类似的问题,并按照以下方式解决了。

 // example.i %module example %include "carrays.i" %array_class(float, floatArray); float * FloatArray(int N); float SumFloats(float * f); 

 # ipython > a = example.floatArray(23) # array generated by swig's class constructor > a  > > a[0] -2.6762280573445764e-37 # unfortunately it is created uninitialized.. > b = example.FloatArray(23) # array generated by function > b  > b[0] --------------------------------------------------------------------------- TypeError Traceback (most recent call last) # ..... TypeError: 'SwigPyObject' object is not subscriptable > #But there is a way to access b!! > p = example.floatArray_frompointer(b) # i found this function by example. and twice tab > p  > > p[0] 0.0 > p[0] = 42 > p[0] 42.0 

幸运的是,所有这些类型(float *,floatArray *和floatArray *的代理)都可以成功传递给C ++函数(例如SumFloats)。

您可能想查看carray.i周围的文档:

%include“carrays.i”%array_class(int,intArray);

http://www.swig.org/Doc2.0/Python.html#Python_nn48

如果你不介意在你的python代码中插入numpy python模块,你可以执行以下操作:

在SWIG界面文件中:

 %{ #define SWIG_FILE_WITH_INIT %} %include "numpy.i" %init %{ import_array(); %} %apply(float ARGOUT_ARRAY1[ANY]) {(float outarray1d[9])}; void rf(float outarray1d[9]); 

只有最后两行是特定于这个例子的,第一个东西是numpy.i的默认值(参见其他地方的numpy.i文档: http ://docs.scipy.org/doc/numpy/reference/swig.interface-file .html )。

在C文件中(也可以在.i文件中内联):

 void rf(float outarray1d[9]) { float _internal_rf[9]; /* ... */ memcpy(outarray1d, _internal_rf, 9*sizeof(float)); } 

然后你有一个函数可以从python调用

 import mymodule a = mymodule.rf() # a is a numpy array of float32's, with len 9 

现在,如果您不想被迫在python项目中拉入numpy模块,那么我建议您检查numpy.i以了解它们如何执行%typemap技巧 – 据我所知,它是通过SWIG完成的类型映射并不固有地绑定到numpy – 应该可以使用元组或列表作为返回值执行相同的技巧。

我不知道你知道多少C – 如果我教你在这里吮鸡蛋,我会道歉…

在plain-ole C中没有Array类。数组总是指向一块内存的指针,而不是本身的“东西”,因此它不能仅仅打印出来。

在这种情况下 – 您的“buf”类型为“double *”。 AFAICRem,如果你想打印存储在“由buf指向的内存”的实际值,你必须释放每一个,例如(在伪代码中):for i = 0 to buflength print buf [i]