我正在试图弄清楚如何使用boost 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 ++ delete。这绝不会发生,所以我泄漏了对象。
我已经尝试过很多技术变种来做到这一点,但从未设法使一切正常。我真的很感激一个完整的例子,可能会展示如何修改上面的例子。
答案 0 :(得分: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);
}