2012-12-25 79 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列表中,因为这看起来像这样的基本操作。如果有人能回答这个问题,我会标记出接受的答案。