微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用boost将C对象传递给python

我试图弄清楚如何使用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.这永远不会发生,所以我泄漏了对象.

我已经尝试了许多变种技术来做到这一点,但从未设法使一切工作.我真的很感激一个完整的例子,可能会展示如何修改上面的例子.

解决方法

我很确定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,a);
    PyGILState_Release(_GILState);
 }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐