Swig,返回一系列双打

时间:2011-04-28 17:19:10

标签: python c arrays return 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.比如<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 个答案:

答案 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);

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

答案 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]