我尝试实现一个应该是可迭代的 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++Stop_Iteration异常转换为 PythonStopIteration异常,我将其添加到 swig 接口文件中:
%typemap(throws) Stop_Iteration %{
  PyErr_SetNone(PyExc_StopIteration);
  SWIG_fail;
%}
但不幸的是,这只在某些情况下有效。例如,以下 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
更新:
阅读此答案后,我找到了解决方案。我认为该__iter__方法在传递给 Python 后有问题。现在我__iter__通过 swig 接口文件直接在 Python 代码中插入。现在看起来像这样:
%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 接口文件中的每个迭代器类没有(或更少)代码的解决方案。