gpt4 book ai didi

python - 用 C 嵌入 Python

转载 作者:太空狗 更新时间:2023-10-30 00:45:55 25 4
gpt4 key购买 nike

我想在 C 应用程序中使用基于事件的 Python 库。我使用官方 C-API 嵌入 Python:http://docs.python.org/2/c-api/index.html#c-api-index

从C调用方法并收集返回值是没有问题的。但是,我不知道如何执行以下操作:

一些 python 库函数将我认为是 python 函数指针的参数作为参数。

是否可以在从 C 调用这些方法时传递 C 函数指针,以便 Python 函数使用 C 函数作为回调?

如果没有,如何让 Python 使用 C 回调?

最佳答案

这比人们想象的要难,但可以做到。

如果您有一个要作为回调提供的 C 函数,您可以使用 PyCFunction_New 将其转换为 Python 可调用函数:

#include <python.h>

static PyObject *my_callback(PyObject *ignore, PyObject *args)
{
/* ... */
}

static struct PyMethodDef callback_descr = {
"function_name",
(PyCFunction) my_callback,
METH_VARARGS, /* or METH_O, METH_NOARGS, etc. */
NULL
};

static PyObject *py_callback;

...
py_callback = PyCFunction_New(&callback_descr, NULL);

如果您想在运行时选择不同的回调,例如提供一个通用的 c_to_python 函数,将 C 回调函数转换为 Python 回调函数。在这种情况下,您需要使用自己的 tp_call 实现扩展类型。

typedef struct {
PyObject_HEAD
static PyObject (*callback)(PyObject *, PyObject *);
} CallbackObject;

static PyObject *
callback_call(CallbackObject *self, PyObject *args, PyObject *kwds)
{
return self->callback(args, kwds);
}

static PyTypeObject CallbackType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"Callback", /*tp_name*/
sizeof(CallbackObject), /*tp_basicsize*/
0, /*tp_itemsize*/
0, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
(ternaryfunc) callback_call, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
};

PyObject *
c_to_python(PyObject (*callback)(PyObject *, PyObject *))
{
CallbackObject *pycallback = PyObject_New(CallbackObject, &CallbackType);
if (pycallback)
pycallback->callback = callback;
return pycallback;
}

这段代码被简单地扩展为也接受一个 user_data 指针;只需将用户数据存储在 CallbackObject 结构中。

关于python - 用 C 嵌入 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13536669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com