Python 提供了以下三个处理 C 类型以及如何处理它们的模块:
-
struct https://docs.python.org/3/library/struct.html对于 C 结构体
-
array https://docs.python.org/3/library/array.html对于数组,例如 C 中的数组
-
ctypes https://docs.python.org/3/library/ctypes.html对于 C 函数,这必然需要处理 C 的类型系统
While ctypes
看起来更通用和灵活(它的主要任务是“Python 的外部函数库”)struct
and array
,当任务是读取二进制数据结构时,这三个模块之间的功能似乎存在显着重叠。例如,如果我想读取 C 结构体
struct MyStruct {
int a;
float b;
char c[12];
};
我可以用struct
如下:
a, b, c = struct.unpack('if12s', b'\x11\0\0\0\x12\x34\x56\x78hello world\0')
print(a, b, c)
# 17 1.7378244361449504e+34 b'hello world\x00'
另一方面,using ctypes同样有效 https://stackoverflow.com/a/1972348(虽然有点冗长):
class MyStruct(ctypes.Structure):
_fields_ = [
('a', ctypes.c_int),
('b', ctypes.c_float),
('c', ctypes.c_char * 12)
]
s = MyStruct.from_buffer_copy(b'\x11\0\0\0\x12\x34\x56\x78hello world\0')
print(s.a, s.b, s.c)
# 17 1.7378244361449504e+34 b'hello world'
(旁白:我确实想知道尾随在哪里'\0'
不过,进入了这个版本……)
在我看来,这违反了“Python之禅”中的原则:
- 应该有一种(最好只有一种)明显的方法来做到这一点。
那么,用于二进制数据处理的几个类似模块的这种情况是如何出现的呢?有历史或现实原因吗? (例如,我可以想象省略struct
完全模块并简单地添加一个更方便的 API 来读取/写入 C 结构ctypes
.)