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);
如果你不介意在你的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]