将 cpython 扩展与 C 结构连接

Interfacing a cpython extension with a C struct

我正在尝试使用我的 C 软件创建一个 python 接口 python 扩展。主要是我需要在 python 中从 C 软件制作一个可访问和修改的大结构,所以我想创建一个 Python class 来做中间,例如在 python my_class.var_int = 1 将反映在下面的结构上。

所以我制作了一个简单的 Python 对象,具有以下从属数据

typedef struct {
    PyObject_HEAD
    struct my_struct *struct_data; 
} CustomObject;

问题是,使用这种方法我需要为我的结构中的每个字段定义一个 getter 和 setter 函数,即使主要是原始字段也是如此(~300)例如 intdouble。而且写那么多函数会容易出错,而且不是很进化。

有一种简单的方法可以定义 class 直接从 Object 结构中存储的成员:

static PyMemberDef Custom_members[] = {
    {"var_int1", T_INT, offsetof(CustomObject, var_int1), 0,
     "first name"},
    {"var_int2", T_int, offsetof(CustomObject, var_int2), 0,
     "last name"},
    {"var_double", T_DOUBLE, offsetof(CustomObject, var_doube), 0,
     "custom number"},
    {NULL}  
};

但在我的例子中它不起作用,因为变量没有直接存储在对象结构中,而是存储在对象引用的结构中。

是否有更简单的方法将结构与 Python 连接起来。或者我是否坚持为我的每个结构字段定义一个 getter 和 setter 函数?

为了能够使用 PyMemberDef,您需要更改 class 的内存布局(struct_data 不再是指针):

typedef struct {
    PyObject_HEAD
    struct my_struct struct_data; 
} CustomObject;

现在offsetof又可以使用了:

static PyMemberDef Custom_members[] = {
    {"var_int1", T_INT, offsetof(CustomObject, struct_data.var_int1), 0,
     "first name"},
     ...
    {NULL}  
};

由于 PyMemberDef 定义中的 offset 对于 class CustomObject 的所有实例应该是相同的,它不能依赖于指针中存储的地址struct_data.

所以如果没有很好的理由,为什么struct_data必须是一个指针,上面的解决方案有很多优点(代码少,不需要内存管理等等)。