0%

boost::python非Python线程回调做法

定义并注册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
/**
* Callback
* @brief 在非Python创建的线程中执行回调
*/
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())
请我喝瓶肥仔快乐水?

欢迎关注我的其它发布渠道