反復可能な 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 インターフェイス ファイル内の各反復子クラスのコードがない (または少ない) ソリューションが望ましいと思います。