定义并注册Callback class
以下Callback是在非Python所创建的线程中回调Python中的方法,所以在执行任何Python相关的调用前,最好先调用PyGILState_Ensure
,另外使用boost::python::call_method
来调用Python对象中的方法。
非Python创建的线程
PyGILState_Ensure
call_method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
class Callback { public: Callback() : m_self(nullptr) { }
explicit Callback(PyObject* self) : m_self(self) { }
Callback(const Callback& other) noexcept : m_self(other.m_self) { incref(); }
Callback(Callback&& other) noexcept { m_self = other.m_self; other.m_self = nullptr; }
Callback& operator=(const Callback& other) noexcept { m_self = other.m_self; incref(); return *this; }
Callback& operator=(Callback&& other) noexcept { m_self = other.m_self; other.m_self = nullptr; return *this; }
virtual ~Callback() { decref(); }
void incref() { if (!m_self) { return; }
PyGILState_STATE state = PyGILState_Ensure(); Py_INCREF(m_self); PyGILState_Release(state); }
void decref() { if (!m_self || !Py_REFCNT(m_self)) { return; }
PyGILState_STATE state = PyGILState_Ensure(); Py_DECREF(m_self); PyGILState_Release(state); }
void dispatch(const std::string message) { if (!m_self) { return; }
PyGILState_STATE state = PyGILState_Ensure(); try { call_method<void>(m_self, "event", std::string(message), boost::python::object()); } catch (const boost::python::error_already_set&) { boost::python::handle_exception(); } catch (const std::exception&) { boost::python::handle_exception(); } PyGILState_Release(state); }
void dispatch(const std::string message, boost::python::dict& data) { if (!m_self) { return; }
PyGILState_STATE state = PyGILState_Ensure(); try { call_method<void>(m_self, "event", std::string(message), data.copy()); } catch (const boost::python::error_already_set&) { boost::python::handle_exception(); } catch (const std::exception&) { boost::python::handle_exception(); } PyGILState_Release(state); }
protected: PyObject* m_self; };
|
1 2 3 4
| BOOST_PYTHON_MODULE(FooModule) { class_<Callback, boost::noncopyable>("Callback", init<PyObject*>()); }
|
补充注册回调方法
下面这个例子会在注册回调函数时启动一个C/C++运行时线程,休眠一秒后执行回调。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void register_callback(Callback& callback) { std::thread([](Callback callback) { std::this_thread::sleep_for(std::chrono::milliseconds(1000));
callback.dispatch("message_one");
PyGILState_STATE state = PyGILState_Ensure(); { boost::python::dict data; data["key"] = "ten"; data["value"] = 10; callback.dispatch("message_two", data); } PyGILState_Release(state);
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); }, callback).detach(); }
|
1 2 3 4 5 6
| BOOST_PYTHON_MODULE(FooModule) { class_<Callback, boost::noncopyable>("Callback", init<PyObject*>());
def("register_callback", register_callback); }
|
Python测试代码
1 2 3 4 5 6 7 8 9
| class MyCallback(FooModule.Callback): def __init__(self): FooModule.Callback.__init__(self, self)
def event(self, message, data=None): print(message) print(data)
FooModule.register_callback(MyCallback())
|