首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用C++嵌入Python

用C++嵌入Python
EN

Stack Overflow用户
提问于 2012-11-24 07:03:53
回答 1查看 1.4K关注 0票数 5

我想在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回调?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-24 07:35:04

这比人们预期的要难,但它是可以做到的。

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

代码语言:javascript
复制
#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回调函数转换为c_to_python回调函数的通用回调函数,这种方法将不起作用。在这种情况下,您需要使用自己的tp_call实现一个扩展类型。

代码语言:javascript
复制
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结构中即可。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13536669

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档