|
2 | 2 |
|
3 | 3 | #include <Python.h> |
4 | 4 |
|
| 5 | +static PyObject *eventLoopJobWrapper(PyObject *jobFn, PyObject *Py_UNUSED(_)) { |
| 6 | + PyObject *ret = PyObject_CallObject(jobFn, NULL); // jobFn() |
| 7 | + Py_XDECREF(ret); // don't care about its return value |
| 8 | + Py_RETURN_NONE; |
| 9 | +} |
| 10 | +static PyMethodDef jobWrapperDef = {"eventLoopJobWrapper", eventLoopJobWrapper, METH_NOARGS, NULL}; |
| 11 | + |
5 | 12 | PyEventLoop::AsyncHandle PyEventLoop::enqueue(PyObject *jobFn) { |
| 13 | + PyObject *wrapper = PyCFunction_New(&jobWrapperDef, jobFn); |
6 | 14 | // Enqueue job to the Python event-loop |
7 | 15 | // https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_soon |
8 | | - PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_soon_threadsafe", "O", jobFn); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue |
| 16 | + PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_soon_threadsafe", "O", wrapper); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue |
9 | 17 | return PyEventLoop::AsyncHandle(asyncHandle); |
10 | 18 | } |
11 | 19 |
|
12 | 20 | PyEventLoop::AsyncHandle PyEventLoop::enqueueWithDelay(PyObject *jobFn, double delaySeconds) { |
| 21 | + PyObject *wrapper = PyCFunction_New(&jobWrapperDef, jobFn); |
13 | 22 | // Schedule job to the Python event-loop |
14 | 23 | // https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.call_later |
15 | | - PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_later", "dO", delaySeconds, jobFn); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue |
| 24 | + PyObject *asyncHandle = PyObject_CallMethod(_loop, "call_later", "dO", delaySeconds, wrapper); // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue |
16 | 25 | if (asyncHandle == nullptr) { |
17 | 26 | PyErr_Print(); // RuntimeError: Non-thread-safe operation invoked on an event loop other than the current one |
18 | 27 | } |
|
0 commit comments