2012-12-25 103 views
2

我有一個C++類,其中一個方法返回一個double *數組,就像它的一個成員變量。我試圖使它成爲Python中的列表。我將它包裝在doubleArray_frompointer中,然後嘗試使用deepcopy將其安全地移出,但當doubleArray超出範圍時,仍然存在問題,它的內存已清理完畢,然後C++類嘗試清理相同的內存內存(儘管這在我創建的gist中沒有顯示)。從swig返回double *作爲python列表

我懷疑我應該用typemaps來做這件事。

什麼,我試圖總結是:

double *foo() { 
    double *toReturn = new double[2]; 
    toReturn[0] = 2; 
    toReturn[1] = 4; 
    return toReturn; 
} 

和接口是:

%module returnList 
%include "returnList.h" 

%include "cpointer.i" 
%pointer_functions(double, doubleP) 

%include "carrays.i" 
%array_class(double, doubleArray); 

%{ 
#include "returnList.h" 
%} 
+0

」類型映射通常不是使用SWIG所需的部分。「也許我在這裏錯過了很明顯的東西? – tsbertalan

回答

3

你說的正確,可以使用類型映射來避免在Python端編寫循環。我舉了一個例子 - 它非常類似於this other answer

%module test 

%typemap(out) double *foo %{ 
    $result = PyList_New(2); // use however you know the size here 
    for (int i = 0; i < 2; ++i) { 
    PyList_SetItem($result, i, PyFloat_FromDouble($1[i])); 
    } 
    delete $1; // Important to avoid a leak since you called new 
%} 

%inline %{ 
double *foo() { 
    double *toReturn = new double[2]; 
    toReturn[0] = 2; 
    toReturn[1] = 4; 
    return toReturn; 
} 
%} 

這裏的類型映射相匹配的名爲foo函數返回double * - 你可以匹配更加廣泛,但隨後會有這樣的功能說錯話的風險,回訪double *並不意味着你返回一個數組大小2.

有了這個類型映射的我可以運行:

Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40) 
[GCC 4.4.5] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import test 
>>> test.foo() 
[2.0, 4.0] 
>>> 

你需要手動將其寫這樣的原因是因爲沒有辦法痛飲推斷的長度從foo返回的數組。它甚至可以在不同的通話間變化「

+0

它在不同的調用之間會有所不同,但是'numRounds'長度是程序參數之一。也就是說,它是我們可以在Python中訪問的一個變量(約200)。這是否意味着我應該在Python中使用循環?但是,不知何故,我仍然必須在swig接口文件或C++代碼中編寫'new',以便Python和C++類都不會嘗試清理相同的內存。 – tsbertalan

+0

[gist](https://gist.github.com/4349180)過於簡單化。我正在返回一個類成員,而不僅僅是一個函數。現在修好了,但它並沒有給我希望的錯誤。 – tsbertalan

+0

我認爲這是問題的正確答案。然而,我真的應該使用std :: vector 而不是double *數組,因爲如果包含std_vector,SWIG會自動將它們包裝爲元組,因此它是可迭代的,並且長度已知。我已經改變了要點來反映這一點。 – tsbertalan

0

我通過返回任何形式的載體 - 或「解決」這個問題不是陣列狀對象,而是通過在Python中重新創建首先生成數組的(簡單)循環。也就是說,我的C++代碼只需要返回單個的雙精度數據,而我的Python代碼將組裝這個數組。

爲了更加明確,我有C++方法double *simulation.run(),這是造成麻煩。我創建了一個新的C++方法double simulation.doRound(),然後通過SWIG在numRounds迭代的Python循環中調用此方法,每次迭代都執行outputs.append(simulation.doRound())

但是,我仍然想知道如何通過SWIG將C/C++ double *數組複製到Python列表中,因爲這看起來像這樣的基本操作。如果有人能回答這個問題,我會標記出接受的答案。