使用SWIG将可迭代C++类传递到Python

2024-09-29 07:22:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试实现一个应该是可迭代的C++类。到目前为止,我写的是:

class XYByFrameIterator {
 public:
  XYByFrameIterator(vector<xy>& precalc) :_precalc(precalc), _current(precalc.begin()), _end(precalc.end()) {}

  XYByFrameIterator* __iter__() { cout << "__iter__" << endl; return this;}

  xy& next() throw (Stop_Iteration) {
    if (_current == _end)
      throw Stop_Iteration();
    xy& ret = *_current;
    _current++;
    return ret; 
  }

 private:
  vector<xy>& _precalc;
  vector<xy>::iterator _current;
  vector<xy>::iterator _end;
};

将自定义C++ +^ {CD1>}转换为Python ^ {< CD2>}异常,我将其添加到SWIG接口文件:

^{pr2}$

但不幸的是,这只在某些情况下有效。例如,下面的python代码按预期打印x/y值。在

it = fa.xyByFrameIterator(43)
for xy in it:
    print(xy.x)
    print(xy.y)

但是如果我直接在循环中实例化迭代器,它会崩溃:

for xy in fa.xyByFrameIterator(43):
    print(xy.x)
    print(xy.y)

输出:

__iter__
44.2233009338
5.83165979385
segmentation fault

更新:

我在读了这篇answer后找到了一个解决方案。我假设在将__iter__方法传递给Python之后,它有问题。现在我通过swig接口文件直接在Python代码中插入__iter__。现在看起来像这样:

%typemap(throws) Stop_Iteration %{
  PyErr_SetNone(PyExc_StopIteration);
  SWIG_fail;
%}
%extend XYByFrameIterator
{
%insert("python") %{
    def __iter__(self):
        return self
%}
}

以及我的c++代码:

class XYByFrameIterator {
 public:
  XYByFrameIterator(vector<xy>& precalc) :_precalc(precalc), _current(precalc.begin()), _end(precalc.end()) {}
  xy& next() throw (Stop_Iteration) {
    if (_current == _end)
      throw Stop_Iteration();
    xy& ret = *_current;
    _current++;
    return ret; 
  }

 private:
  vector<xy>& _precalc;
  vector<xy>::iterator _current;
  vector<xy>::iterator _end;
};

这很好地工作,但是我更喜欢swig接口文件中每个迭代器类没有(或更少)代码的解决方案。在


Tags: 代码returncurrentendstopthrowprintvector