C++/boostpython类重写
嗯。我的问题其实很简单。这是一个框架侦听器类和python包装器类,然后由boost python使用: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() {}
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";
}