从swig中返回double *作为python列表

时间:2012-12-25 19:22:53

标签: c++ python pointers swig

我有一个C ++类,其中一个方法返回一个double *数组,它是其成员变量之一。我试图将其作为Python中的列表进行访问。我将它包装在doubleArray_frompointer中,然后尝试使用deepcopy安全地将其从那里取出,但是当doubleArray超出范围,清除内存,然后清除时,我仍然会遇到问题C ++类试图清理相同的内存(虽然我创建的gist中没有显示)。

我怀疑我应该使用打字机做这件事。

我想要包装的是:

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"
%}

2 个答案:

答案 0 :(得分: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;
}
%}

这里的typemap与一个名为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]
>>>

您需要像这样手动编写它的原因是因为SWIG无法推断您从foo返回的数组的长度。它甚至可能因电话而异。

答案 1 :(得分:0)

我'解决'问题不是通过返回任何类型的矢量或类似数组的对象,而是通过在Python中重新创建首先生成数组的(简单)循环。也就是说,我的C ++代码只需返回单个双精度数,而我的Python代码将汇总列表。

为了更加明确,我有C ++方法double *simulation.run(),这导致了麻烦。我创建了一个新的C ++方法double simulation.doRound(),然后在numRounds次迭代的Python循环中通过SWIG调用它,每次迭代都进行outputs.append(simulation.doRound())

但是,我仍然想知道如何通过SWIG将C / C ++ double *数组复制到Python列表,因为这看起来像是一个基本的操作。如果有人可以回答这个问题,我会标记为接受的答案。