2016-12-27 75 views
0

好的。我的問題其實很簡單。這是一個幀監聽器類和python包裝類,然後被升壓蟒:C++/Boost Python類重寫

class FrameListener 
    { 
    public: 

     struct FrameEvent 
     { 
      double TimeSinceLastEvent; 
      double TimeSinceLastFrame; 
     }; 

     FrameListener() {} 
     ~FrameListener() {} 

     virtual void FrameStart(FrameEvent& evt) = 0; 
     virtual void FrameEnd(FrameEvent& evt) = 0; 
     virtual void OnFrame(FrameEvent& evt) = 0; 
    }; 

    class FrameListener_PyWrapper : public FrameListener, public boost::python::wrapper<FrameListener> 
    { 
    public: 
     FrameListener_PyWrapper() {}  
     ~FrameListener_PyWrapper(); 

     void FrameStart(FrameEvent& evt); 
     void FrameEnd(FrameEvent& evt); 
     void OnFrame(FrameEvent& evt); 
    }; 

類被再包以提高蟒:

class_<SL_Engine::FrameListener::FrameEvent>("FrameEvent") 
     .def_readonly("TimeSinceLastEvent", &SL_Engine::FrameListener::FrameEvent::TimeSinceLastEvent) 
     .def_readonly("TimeSinceLastFrame", &SL_Engine::FrameListener::FrameEvent::TimeSinceLastFrame); 

    class_<SL_Engine::FrameListener_PyWrapper, boost::noncopyable>("FrameListener") 
     .def("OnFrame", pure_virtual(&SL_Engine::FrameListener::OnFrame)) 
     .def("FrameStart", pure_virtual(&SL_Engine::FrameListener::FrameStart)) 
     .def("FrameEnd", pure_virtual(&SL_Engine::FrameListener::FrameEnd)) 
     ; 

這可以在python來創建自己的幀被重寫監聽器類:

class SimpleListen(FrameListener): 
def __init__(self): 
    pass 
def FrameEndd(self, evt): 
    pass 

然後創建新SimpleListener類的實例和「註冊」它與CORE_ENGINE.AddFrameListener()函數的引擎。該函數然後使用boost :: python :: extract()來提取它,並將其放在幀監聽器的std :: vector上,然後每幀執行它。這很好,但如果我忘記在簡單的類中定義base或拼寫錯誤,顯然會導致崩潰。我已經在boost :: python或C/Python API中搜索了google,我如何測試基類是否正確定義。 AddFrameListener接受PyObject *參數。我想先測試PyObject是否是類類型。如果您不小心嘗試輸入一個整數值或字符串,程序將識別該錯誤並顯示該對象不是類類型的消息。如果它是類類型,我想測試它是否具有基類,並且它是否可以提取到FrameListener_PyWrapper *。後來我想測試每個單獨的函數(FrameStart,FrameEnd和OnFrame),如果它們在python類中被覆蓋並且參數匹配。我如何從python函數獲取參數列表?如果任何來自python類的函數沒有被覆蓋,它會給我一個警告。如果參數不匹配,並且您嘗試撥打電話:

if (boost::python::override f = this->get_override("FrameEnd")) 
    { 
     f(evt); 
     return; 
    } 

這會導致崩潰,但沒有任何有關錯誤的信息。我想在調用AddFrameListener函數時檢查參數是否匹配,如果任何函數沒有正確覆蓋,則引擎將不會調用它們保存信息。

回答

0

這次崩潰可能與您在沒有GIL鎖定的情況下調用Python的事實有關。您應該鎖定每次你用Python對象進行交互:

if (override fe = this->get_override("FrameEnd")) 
{ 
    PyLockGIL lock; 
    try 
    { 
     fe(); 
     return; 
    } 
    catch (const error_already_set&) 
    { 
     std::cout << "Exception in FrameEnd in application"; 
     PyErr_Print(); 
    } 
} 
else 
{ 
    std::cout << "FrameEnd called but not overridden"; 
} 
:您回調成Python之前

/* 
This RAII structure ensures that threads created on the native C side 
adhere to the laws of Python and ensure they grab the GIL lock when 
calling into python 
*/ 
struct PyLockGIL 
{ 

    PyLockGIL() 
     : gstate(PyGILState_Ensure()) 
    { 
    } 

    ~PyLockGIL() 
    { 
     PyGILState_Release(gstate); 
    } 

    PyLockGIL(const PyLockGIL&) = delete; 
    PyLockGIL& operator=(const PyLockGIL&) = delete; 

    PyGILState_STATE gstate; 
}; 

然後用它