本文介绍了如何使用 Python 的 ctypes 准确映射模块 C 语言中的结构(如 typedef struct 还有指针的别名),重点演示 ctypes.Structure 创建相应指针类型的定义方法和方法。
本文介绍了如何使用 python 的 ctypes 准确映射模块 c 语言中的结构(如 typedef struct 还有指针的别名),重点演示 `ctypes.structure` 创建相应指针类型的定义方法和方法。
在 Python 中通过 ctypes 调用 C 在动态库中,往往需要将 C 头文件中定义的结构(特别是带) typedef 别名结构)精确还原为 Python 可操作对象如下。 C 以头文件片段为例:
typedef struct {
void *Handle;
} RESHANDLE, *PRESHANDLE;该定义声明了一个匿名结构,并给出了两个别名:RESHANDLE(结构体类型本身)和 PRESHANDLE(指结构体的指针类型)。
在 ctypes 中,应继承 ctypes.Structure 类,并通过 _fields_ 类变量声明成员的名称和类型。注:_fields_ 每个元素必须是元组的列表(即使只有一个字段) (name, type) 形式。void * 在 ctypes 中对应 ctypes.c_void_p。
正确实现如下:
import ctypes as ct
class RESHANDLE(ct.Structure):
_fields_ = [("Handle", ct.c_void_p)]
PRESHANDLE = ct.POINTER(RESHANDLE)✅ 关键说明:
- _fields_ 类属性必须是列表或元组,建议使用列表来提高可读性(如 [("Handle", ct.c_void_p)]);
- ct.POINTER(RESHANDLE) 类型对象(非实例)可用于函数参数声明、返回值注释或返回 ct.cast() 等场景;
- 如果结构体的后续扩展包含其他字段(如 int id; char name[32];),只需按顺序添加 _fields_ 中间,类型分别对应 ct.c_int、ct.c_char * 32。
⚠️ 注意事项:
- 不要将 _fields_ 写成 ('Handle', ct.c_void_p)(单元元素元组容易漏逗号导致语法错误);
- RESHANDLE 实例默认不自动初始化字段,建议显式赋值(如 obj = RESHANDLE(); obj.Handle = some_ptr);
- 若需兼容 32/64 位平台,c_void_p 指针尺寸已自动适应,无需手动切换。
掌握这种模式后,可以无缝对接各种模式 C SDK 中间的句柄结构和配置结构是安全高效的 Python-C 互动奠定了坚实的基础。