2013-03-25 65 views
0

我用SWIG包裝了一個C++類和一個C++函數。SWIG包裝從Python創建的C++對象過早刪除

class Module { ... }; 
void register_module(Module *m); 

功能register_module()會將給定模塊中的全局列表,使得來自然後在C++代碼保持模塊上的指針,並使用它。

現在,下面的Python代碼,從嵌入式Python解釋器運行,崩潰

>>> register_module(Module()) 

在另一方面,下面的Python代碼不會崩潰

>>> m = Module() 
>>> register_module(m) 

顯然,原因是在第一種情況下,對象是由python收集的垃圾,而在第二種情況下則不是。

什麼是防止python刪除在第一種情況下創建並由C++代碼使用的匿名對象的最佳方法?

在register_module()函數中,是否有辦法獲得關聯的python代理對象的暫掛,然後增加其引用計數?我知道這是可能的,如果有問題的類可以交叉轉換成Swig :: Director類,但是假設我們有一個在python中定義的Module子類的實例,它不是這裏的情況)。

回答

0

解決方案。
步驟1:向Module類添加一個成員,並添加兩個方法。

class Module { 
public: 
    PyObject *obj; 
    void incref() { Py_INCREF(obj); } 
    void decref() { Py_DECREF(obj); } 
    ... 
}; 

步驟2:增加在register_module引用計數()。

void register_module(Module *m) { 
    m->incref(); 
    ... 
} 

(不要忘記某處降低它)

步驟3:入侵的SWIG生成的包裝,在模塊對象從Python的構造成與obj成員設置爲的PyObject包裝。

在痛飲生成的文件ModulePYTHON_wrap.cxx,找到:

SWIGINTERN PyObject *_wrap_new_Module(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { 
    PyObject *resultobj = 0; 
    ... 
    Module *result = 0 ; 
    ... 
    if (arg1 != Py_None) { 
    /* subclassed */ 
    result = (Module *)new SwigDirector_Module(arg1); 
    } else { 
    result = (Module *)new Module(); 
    } 

    resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Module, SWIG_POINTER_NEW | 0); 
    return resultobj; 
    ... 
} 

插入result->obj =resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Module, SWIG_POINTER_NEW | 0);
我們得到:

result->obj = resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Module, SWIG_POINTER_NEW | 0); 

步驟4:指示SWIG自動實現修復在生成的包裝器中。

在接口文件中添加以下typemap聲明。

%typemap(out) Module* { 
    result->obj = $result = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Module, SWIG_POINTER_NEW | 0); 
} 

這有效地覆蓋了默認情況下生成的用於包裝新Module對象的代碼。

+0

如果班級有導演,則應該在導演python對象上。然後,typemap代碼將變爲:$ result = SWIG_NewPointerObj(SWIG_as_voidptr(result),SWIGTYPE_p_Module,SWIG_POINTER_NEW | 0); Swig :: Director * dr = dynamic_cast (result); result-> obj = dr? dr-> swig_get_self():$ result; – user2179288 2013-03-28 19:46:35