2011-04-28 72 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 - 應該可以用元組或列表作爲返回值來做同樣的技巧。