从swig返回双*作为python列表

return double * from swig as python list

本文关键字:作为 python 列表 swig 返回      更新时间:2023-10-16

我有一个c++类,其中一个方法返回一个double *数组,这是它的一个成员变量。我试着让它在Python中作为一个列表访问。我把它包装在一个doubleArray_frompointer中,然后尝试使用deepcopy让它安全地离开那里,但是当doubleArray超出范围时,我仍然有问题,它的内存被清理,然后c++类试图清理相同的内存(尽管这在我创建的要点中没有显示)。

我怀疑我应该用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"
%}

你说typemap可以用来避免在Python端编写循环,这是正确的。我把一个例子放在一起——它和另一个答案非常相似。

%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的数组的函数,则有做错误事情的风险。

使用这个typemap,我可以运行:
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返回的数组的长度。

我不是通过返回任何类型的向量或数组类对象来"解决"这个问题,而是通过在Python中重新创建最初生成数组的(简单)循环来解决这个问题。也就是说,我的c++代码只需要返回单个双精度对象,而我的Python代码将组装该列表。

稍微显式一点,我有c++方法double *simulation.run(),这引起了麻烦。我创建了一个新的c++方法double simulation.doRound(),然后在numRounds迭代的Python循环中通过SWIG调用它,每次迭代执行outputs.append(simulation.doRound())

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