我正在使用 Python C API 将 C 代码与 Python 集成,并且我需要使用附加数据注册回调函数。具体来说,我想将额外的数据传递给我的回调函数,以便在调用回调时可以访问它。
这是我的问题的简化版本:
我需要使用Python C API在Python解释器中注册一些函数。我的回调函数应该具有以下签名:
PyObject* callback(PyObject* self, PyObject* args);
但是,我还需要向此回调传递一些额外的数据。例如,在 Tcl 库中,有一个函数 Tcl_CreateCommand 允许传递像这样的附加客户端数据(https://www.astro.princeton.edu/~rhl/Tcl-Tk_docs/tcl8.0a1/CrtCommand.3)。 html):
Tcl_CreateCommand(interp, command_name, callback, client_data);
就我而言,我想使用 Python C API 实现类似的功能。如何将附加数据传递给 Python C API 中的回调函数?
这是我到目前为止所拥有的:
#include <Python.h>
// Define a structure to hold additional data
typedef struct {
int some_value;
} CallbackData;
// Define the callback function
PyObject* callback(PyObject* self, PyObject* args) {
// Retrieve and use the additional data here
// ...
}
// Function to register the callback
void register_callback(PyObject* module) {
// Setup additional data
CallbackData* data = (CallbackData*)malloc(sizeof(CallbackData));
data->some_value = 42;
// Where to pass the data to access it from callback?
PyMethodDef* foo_def = new PyMethodDef{"foo", callback, METH_VARARGS, "Docs"}
PyObject* foo = PyCFunction_New(foo_def, NULL);
PyModule_AddObject(module, "foo", foo);
}
如何修改此代码以确保回调函数在调用时可以访问额外的数据(本例中为 CallbackData)?
任何建议或示例将不胜感激!
在Tcl库中,有一个函数Tcl_CreateCommand允许传递额外的客户端数据
有点。 自定义 Tcl 命令自动可以访问指向运行该命令的 Tcl 解释器的指针,以及指向为执行该命令提供数据上下文的客户端数据对象的指针。 重要的是,客户端数据是它自己的东西,不会计入命令的参数中。 几乎就像每个自定义 Tcl 命令都是一个闭包。
我想用Python C API 实现类似的功能。如何将附加数据传递给 Python C API 中的回调函数?
Python 没有这种“客户端数据”上下文的明确概念。 无论是在纯 Python 中还是在 C API 中。 它确实有闭包,但那些闭包是基于定义特定函数的上下文,而你的闭包完全是在Python本身之外定义的。 您的选择包括:
该函数将能够通过模块的命名空间字典访问其模块的变量,因此您可以将所需的上下文数据放入这样的变量中(作为Python对象)。 这允许您在运行时替换 Python 中的不同对象。
扩展模块可以在模块初始化期间设置数据,并将其(或指向它的指针)存储在模块的 C 源代码中定义的静态变量中。 然后,C 函数可以通过正常的 C 机制从那里访问它。 在这种情况下,如果您希望能够从 Python 替换或修改客户端数据,那么您需要为此目的创建额外的函数。
该函数可以是完全正常的,接受客户端数据作为普通位置或命名参数。 然后,您可以完全在 Python 端定义客户端数据,并将本机函数调用包装在普通的 Python 闭包中,该闭包向函数(闭包的)调用者透明地提供客户端数据。