【问题标题】:C++/Boost Python class overridingC++/Boost Python 类覆盖
【发布时间】:2017-05-11 19:35:18
【问题描述】:

好的。我的问题其实很简单。这是一个 frame listener 类和 python wrapper 类,然后被 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);
    };

然后包装类以增强 python:

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 或拼写错误,显然会导致崩溃。我在 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 c++ python-2.7 boost


    【解决方案1】:

    崩溃可能与您在没有锁定 GIL 的情况下调用 Python 的事实有关。每次与 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";
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 1970-01-01
      • 2012-12-17
      • 2020-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多