4

ブースト python を使用して c++ でオブジェクトを作成し、それを Python に渡す方法を理解しようとしています。私はこれを行うことができましたが、ガベージコレクションを実行できません。

クラス A が C++ のどこかで定義されていると想像してください。passNewAToPython() 関数は、コード内の別の場所から呼び出され、A オブジェクトを作成し、それを Python のコールバック関数に渡します。その特定のインスタンスをコピーではなく python に渡したいので、ptr() を使用します

static PyObject * pythonCallbacks;

void passNewAToPython()
{
  A * a = new A();
  PyGILState_STATE _GILState = PyGILState_Ensure();
  //Should really use a try catch here too but lets ignore that for now
  boost::python::call_method<void>(pythonCallbacks, "newA", boost::python::ptr(a));
  PyGILState_Release(_GILState);
}

void initmodule(PyObject* userCallCallbacks_)
{
   PyEval_InitThreads();

   pythonCallbacks = userCallCallbacks_;
}

BOOST_PYTHON_MODULE(mymodule)
{
    def("initmodule", initmodule);

    class_<A, boost::noncopyable>("A", init<>());
}

Python コード

import mymodule

class pythonCallbacks(object):
    a_list = [];
    def newA(self, a):
         self.a_list.append(a)

callbacks = pythonCallbacks()
mymodule.initmodule(callbacks)

newA コールバックが呼び出された後、しばらくしてから想像してみてください。インスタンスが格納されると予想される唯一の場所は、a_list です。したがって、a_list から a を削除すると、new で作成したオブジェクトに対して c++ の削除が呼び出されることが予想されます。それは決して起こらないので、オブジェクトをリークします。

これを行うためにさまざまな手法を試しましたが、すべてを機能させることはできませんでした。おそらく上記の例を変更する方法を示す完全な例をいただければ幸いです。

4

1 に答える 1

1

ptr()指しているオブジェクトの寿命とは何の関係もないと確信しています。使用する場合、寿命を管理するのは完全にあなた次第です。(これを使用することは、PyCObject を使用するようなものだと思います。)

できることは、 A のポインター型を shared_ptr に定義することです (boost または std は関係ありません)。このようなもの:

class_<A, shared_ptr<A>, boost:noncopyable>("A", init<>());

次に、ファクトリ関数にこれを実行させることができます。

void passNewAToPython()
{
    A * a = make_shared<A>();
    PyGILState_STATE _GILState = PyGILState_Ensure();     
    //Should really use a try catch here too but lets ignore that for now
    boost::python::call_method<void>(pythonCallbacks, "newA", a);
    PyGILState_Release(_GILState);
 }
于 2012-12-16T20:25:49.650 に答える