Swig返回双精度数组
我知道,解决某些问题的方法通常有很多种。但是在这里,我知道我想要的方式,但我在用Python和SWIG时却无法让它工作...
我有一个C语言的函数,它返回一个双精度浮点数的数组:
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]
无论我怎么做,我在这里总是遇到一些概念上的问题——我总是得到类似 <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);
}
}
但我仍然无法得到我想要的结果。有没有人能提供一个简单的代码示例来完成这个任务?
5 个回答
你可能想看看关于carray.i的文档:
%include "carrays.i" %array_class(int, intArray);
我遇到过类似的问题,以下是我解决的办法。
// 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)。
第一个问题是你的类型映射不匹配。你需要一个 %typemap(out) double * { ... }
,因为你的函数返回的是一个指向双精度浮点数的指针,而不是一个双精度数组。
如果你的列表是固定大小的(也就是一个整数常量),就像你给出的例子那样(我猜这不是你想要的),你可以简单地按照我上面说的更改类型映射,并把 $1_dim0
替换为固定的大小。
否则,你的问题在于你的 %typemap(out) double *
根本无法知道你的参数 int x
的值。你可以返回一个结构体,里面同时包含指针和大小。这样你就可以轻松定义一个类型映射,把它转成一个列表(或者NumPy数组,具体可以参考我对 如何用SWIG、Cython或ctypes在Python中访问C结构体的数组成员的回答)。
顺便提一下,在C语言中返回固定大小的数组是不可能的(可以参考这个回答: 声明一个C函数返回数组),所以 %typemap(out) double [ANY] { ... }
永远无法匹配。