2012-12-04 65 views
3

我試圖找出如何使用升壓蟒蛇在C++中創建一個對象,並將其傳遞到Python的蟒蛇。我設法做到這一點,但不能讓垃圾收集發生。傳遞C++對象與升壓

想象A類是用C某處定義++。 passNewAToPython()函數是從代碼中的其他地方調用的,該代碼創建一個A對象,然後將其傳遞給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) 

現在想象一段時間紐瓦調用回調函數後後。我期望存儲實例的唯一地方是在a_list中。所以如果我從a_list中刪除一個,那麼我會期望在我用new創建的對象上調用C++ delete。這絕不會發生,所以我會泄漏物體。

我試過技術的許多變體要做到這一點,但從來沒有設法使一切工作。我真的很感激一個完整的例子,可能會展示如何修改上面的例子。

+0

我不熟悉的boost :: Python,但你在哪裏釋放的python的對象引用計數C++方面? – Arafangion

+0

如何釋放C++端的python對象引用計數?我已經看到BOOST和Python API命令都用於增加/減少引用計數,但它們只能在python對象上運行。這裏的python對象是在call_method函數中創建的。 call_method完成後,我希望對象的唯一引用通過Python存在,以便當所有的Python引用都不存在時,對象被刪除。我曾嘗試從指針創建一個boost :: python :: object,然後調用增加/減少,但我通常只是得到一個崩潰。 – Dave

+1

所以你具體轉移對象的所有權,在這種情況下,你應該遞減引用計數,除非目標方法不增加引用計數。 – Arafangion

回答

0

我敢肯定,ptr()無關與對象的生命週期所指向。如果你使用它,管理這個生命週期完全取決於你。 (我相信使用它就像使用PyCObject。)

你可以做的就是定義A的指針類型是一個shared_ptr(或升壓或性病,無所謂)。事情是這樣的:

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); 
}