我知道,通常有很多方法可以解决某些问题。但是在这里我知道我希望它采用哪种方式,但我无法使用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.比如<Swig Object of type 'double *' at 0xFABCABA12>
我尝试在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);
}
}
但我仍然无法按要求取出我的结果。有没有人有一个简单的代码示例来实现这个任务?
答案 0 :(得分:4)
第一个问题是你的typemap不匹配,你需要一个%typemap(out) double * { ... }
,因为你的函数返回一个指向double而不是double数组的指针。
如果您的列表具有固定大小(即整数字面),如您给出的示例(我假设不是您想要的那样),您只需更改上面给出的类型映射并交换$1_dim0
固定的大小。
否则您的问题是您的%typemap(out) double *
无法知道参数int x
的值。您可以返回一个包含指针和大小的结构。然后,您可以轻松定义类型映射以将其转换为列表(或NumPy数组,另请参阅我对Wrap C struct with array member for access in python: SWIG? cython? ctypes?的响应)。
顺便说一句,无法在C中返回固定大小的数组(另请参阅此答案:Declaring a C function to return an array),因此%typemap(out) double [ANY] { ... }
永远不会匹配。
答案 1 :(得分:3)
我遇到了类似的问题并以下列方式解决了这个问题。
// 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
<example.floatArray; proxy of <Swig Object of type 'floatArray *' at 0x2e74180> >
> a[0]
-2.6762280573445764e-37 # unfortunately it is created uninitialized..
> b = example.FloatArray(23) # array generated by function
> b
<Swig Object of type 'float *' at 0x2e6ad80>
> 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
<example.floatArray; proxy of <Swig Object of type 'floatArray *' at 0x2e66750> >
> p[0]
0.0
> p[0] = 42
> p[0]
42.0
幸运的是,所有这些类型(float *,floatArray *和floatArray *的代理)都可以成功传递给C ++函数(例如SumFloats)。
答案 2 :(得分:1)
您可能想查看有关carray.i的文档:
%包含“carrays.i” %array_class(int,intArray);
答案 3 :(得分:1)
如果您不介意在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绑定 - 应该可以使用元组或列表作为返回值执行相同的技巧。
答案 4 :(得分:-4)
我不知道你知道多少C - 如果我教你在这里吃鸡蛋,那么道歉......
在plain-ole C中没有Array类。数组总是指向一块内存的指针,而不是本身的“东西”,因此不能单独打印出来。
在这种情况下 - 您的“buf”类型为“double *”。 AFAICRem,如果你想打印存储在“由buf指向的内存”的实际值,你必须解除分配每个,例如(在伪代码中):for i = 0 to buflength print buf [i]