2011-04-28 73 views
8

我知道,通常有很多方法可以解决某些问题。但在这里,我知道我想拥有它哪种方式,但我无法使其与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'函数写入输入数组。现在,我想获得一大口,Python包装,它可能被用来作为:

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

无论我做什么,我有一些概念上的问题,在这里 - 我总是得到某事物像<Swig Object of type 'double *' at 0xFABCABA12>

我想在我的SWG文件来定义一些typemaps:

%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

ups,是的,这是我所面对的实际代码的超小部分。对困惑感到抱歉。 – user701370 2011-04-28 17:54:14

回答

-3

我不知道你有多么Ç知道 - 所以道歉,如果我教你在这里班门弄斧......

有以纯OLE C.没有Array类数组始终是一个指向一段内存的指针,本身不是“事物”,因此不能单独打印出来。

在这种情况下 - 您的“buf”是“double *”类型。 AFAICRem,如果你想打印出存储在“buf指向的内存”中的实际值,你必须重新分配每一个值(例如伪代码):对于i = 0到buflength打印buf [i]

+1

错误:请阅读[c-faq]的第6部分(http://c-faq.com/)。数组不是指针;指针不是数组。 – pmg 2011-05-25 21:26:37

+0

是的,它们并不完全相同......那不是我的观点。关键是在c中,你不能这么做,比如说“my_array.length” 在C中,一个数组不知道它有多大(在许多OO语言中它是这样做的),并且你不能合理地打印它以上述方式出来。你必须自己做这项工作。 – 2011-05-26 10:20:06

1

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

%包括 “carrays.i” %array_class(INT,intArray);

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

+1

我看不出这些如何工作的输出(输入案例从文档很清楚)。你能举个例子吗? – kynan 2011-05-30 19:35:32

4

的第一个问题是,你的类型表不匹配,你需要一个%typemap(out) double * { ... }因为你的函数返回一个指针翻一番,而不是一个双阵列。

如果您的列表是固定大小(即整数字面量),如您给出的示例(我认为它不是您想要的),您可以简单地更改上面给出的类型映射表,并将$1_dim0替换为固定大小。

否则你的问题是你的%typemap(out) double *不可能知道你的参数int x的价值。你可以返回一个包含指针和大小的结构体。然后你可以很容易地定义一个typemap来将它转换成一个列表(或一个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] { ... }永远不会匹配。

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 

幸运的是,所有这些类型的(浮动*,floatArray *和floatArray *的代理)可以被成功地传递到C++函数(如SumFloats)。

1

如果你不介意的numpy的Python模块中拉在你的Python代码,你可以做到以下几点:

在痛饮接口文件:

%{ 
#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)); 
} 

然后你有,你可以从蟒蛇现在叫为

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

的功能,如果你不我不希望被迫在你的python项目中使用numpy模块,那么我建议你检查一下numpy.i,看看它们是如何处理%typemap的技巧的 - 据我所知,它是用SWIG类型映射完成的,而不是固有的绑定numpy - 应该可以用元组或列表作为返回值来做同样的技巧。