Вы не можете. Функции C / C ++ не могут напрямую обращаться к функциям Python - этот прототип функции, вероятно, ожидает указатель на C. Python будет передавать ему указатель на свою внутреннюю структуру данных для этой конкретной функции.
Настало время создать расширение C для Python, чтобы обернуть эту DLL и открыть ее для Python. По сути, вы должны сделать так, чтобы обратный вызов C вызывал обратный вызов Python, так как это можно сделать . Чтобы быть более понятным, то, что вы хотите достичь, это:
| This side is C land i.e. "real" addresses
|
Python objects --> C extension -- register callback with --> DLL
| |
in the python | Calls callback
| |
interpreter <-------------- Callback in C extension <-------
|
Ниже приведено очень быстрое объяснение построения вызова функции Python из C. Вам нужно будет создать этот код с помощью MSVC (или альтернативного инструмента), который использовался для сборки вашего дистрибутива Python; используйте depends.exe
, чтобы узнать, с каким msvcXX.dll
он связан.
Глобальное состояние обычно считается плохим, но для простоты я использовал его:
static PyObject* pyfunc_event_handler = NULL;
static PyObject* pyfunc_event_args = NULL;
Затем я добавил функцию set set handler, чтобы упростить процесс установки обратного вызова. Однако вам не нужно этого делать, вам просто нужно
static PyObject* set_event_handler(PyObject *self, PyObject *args)
{
PyObject *result = NULL;
PyObject *temp;
Следующая строка является важной - я разрешаю передавать два объекта python (O
аргументы PyArg_ParseTuple
. Один объект содержит функцию, другой - ее параметры.
if (PyArg_ParseTuple(args, "OO", &temp, &pyfunc_event_args)) {
if (!PyCallable_Check(temp)) {
PyErr_SetString(PyExc_TypeError, "parameter must be a function");
return NULL;
}
Сортировка ссылок. Python нуждается в вас, чтобы сделать это.
Py_XINCREF(temp); /* Add a reference to new func */
Py_XDECREF(pyfunc_event_handler); /* Dispose of previous callback */
pyfunc_event_handler = temp; /* Remember new callback */
/* Boilerplate to return "None" */
Py_INCREF(Py_None);
result = Py_None;
}
return result;
}
Затем вы можете позвонить в другое место с помощью:
PyObject* arglist = Py_BuildValue("(O)", pyfunc_event_args);
pyobjresult = PyObject_CallObject(pyfunc_event_handler, arglist);
Py_DECREF(arglist);
Не забудьте DECREF
, вам нужен Python для gc arglist.
Из python использовать это так же просто, как:
set_event_handler(func, some_tuple)
Где func имеет подходящие параметры:
def func(obj):
/* handle obj */
Вещи, которые вы, вероятно, хотите прочитать: