私はC++でPythonのCAPI(2.7)を使用して、Pythonツリー構造をC++ツリーに変換しています。コードは次のようになります。
Pythonツリーは、子のリストを持つクラスとして再帰的に実装されます。リーフノードは単なるプリミティブ整数です(クラスインスタンスではありません)
モジュールをロードし、ここのコードを使用してC ++からpythonメソッドを呼び出します。これにより、ツリーのインスタンスpython_treeがC++のPyObjectとして返されます。
取得したPyObjectを再帰的にトラバースします。子のリストを取得するには、次のようにします。
PyObject* attr = PyString_FromString("children"); PyObject* list = PyObject_GetAttr(python_tree,attr); for (int i=0; i<PyList_Size(list); i++) { PyObject* child = PyList_GetItem(list,i); ...
非常に簡単で、PyObject_GetAttr(Objects / object.c:1193ですが、APIコードが表示されません)の呼び出しで、最終的にセグメンテーション違反が発生するまで機能します。これは、ツリーの最後のリーフノードへの訪問時に発生するようです。
問題を特定するのに苦労しています。C APIで再帰を行うための特別な考慮事項はありますか?Py_INCREF / Py_DECREFを使用する必要があるのか、これらの関数などを使用する必要があるのかわかりません。正直に言うと、APIがどのように機能するのか完全には理解していません。どんな助けでも大歓迎です!
編集:いくつかの最小限のコード:
void VisitTree(PyObject* py_tree) throw (Python_exception)
{
PyObject* attr = PyString_FromString("children");
if (PyObject_HasAttr(py_tree, attr)) // segfault on last visit
{
PyObject* list = PyObject_GetAttr(py_tree,attr);
if (list)
{
int size = PyList_Size(list);
for (int i=0; i<size; i++)
{
PyObject* py_child = PyList_GetItem(list,i);
PyObject *cls = PyString_FromString("ExpressionTree");
// check if child is class instance or number (terminal)
if (PyInt_Check(py_child) || PyLong_Check(py_child) || PyString_Check(py_child))
;// terminal - do nothing for now
else if (PyObject_IsInstance(py_child, cls))
VisitTree(py_child);
else
throw Python_exception("unrecognized object from python");
}
}
}
}