如何在 Python C API 中将额外数据传递给回调函数?

问题描述 投票:0回答:1

我正在使用 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)?

任何建议或示例将不胜感激!

python c callback cpython
1个回答
0
投票

在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 闭包中,该闭包向函数(闭包的)调用者透明地提供客户端数据。

© www.soinside.com 2019 - 2024. All rights reserved.