C++/boostpython类重写

C++/boostpython类重写,python,c++,python-2.7,boost,Python,C++,Python 2.7,Boost,嗯。我的问题其实很简单。这是一个框架侦听器类和python包装器类,然后由boost python使用: class FrameListener { public: struct FrameEvent { double TimeSinceLastEvent; double TimeSinceLastFrame; }; FrameListener() {}

嗯。我的问题其实很简单。这是一个框架侦听器类和python包装器类,然后由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))
        ;
然后创建新SimpleListener类的实例,并使用CORE_engine.AddFrameListener()函数将其“注册”到引擎。然后,该函数使用boost::python::extract()将其提取出来,并将其放在帧侦听器的std::vector上,然后每帧执行一次。这非常有效,但如果我忘记在简单类中定义base或拼写错误,显然会导致崩溃。我在google上搜索了boost::python或C/python API,如何测试基类是否正确定义。AddFrameListener接受PyObject*参数。我想先测试PyObject是否为类类型。如果您不小心尝试输入一个整数值或字符串,程序将识别错误并提示对象不是类类型。若它是类类型,我想测试它是否有基类,是否可以提取到FrameListener_PyWrapper*。稍后,我想测试每个单独的函数(FrameStart、FrameEnd和OnFrame)是否在python类中被重写,以及参数是否匹配。如何从python函数中获取参数列表?如果python类中的任何函数未被重写,它将给我一个警告。如果参数不匹配,您尝试调用:

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

这将导致崩溃,而没有任何有关错误的信息。我想在调用AddFrameListener函数时检查参数是否匹配,并保存信息,如果任何函数未正确重写,引擎将不会调用它们。

崩溃可能与您在调用Python时没有锁定GIL有关。每次与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;
};
然后在回调到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";
}
if(override fe=this->get_override(“FrameEnd”))
{
PyLockGIL锁;
尝试
{
fe();
返回;
}
捕获(常量错误\u已设置&)
{
标准::cout
    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";
}