gpt4 book ai didi

Python:struct 和 array 与 ctypes 中的相似功能

转载 作者:行者123 更新时间:2023-11-28 22:16:43 25 4
gpt4 key购买 nike

Python 提供了以下三个模块来处理 C 类型以及如何处理它们:

  • struct对于 C 结构
  • array对于数组,例如 C 中的数组
  • ctypes对于 C 函数,这必然需要处理 C 的类型系统

虽然 ctypes 看起来比 structarray 更通用和灵活(它的主要任务是“Python 的外部函数库”),当任务是读取二进制数据结构时,这三个模块之间的功能似乎有很大的重叠。例如,如果我想读取 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 works equally well (虽然有点冗长):

 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 之禅”中的原则:

  1. There should be one—and preferably only one—obvious way to do it.

那么,这些用于二进制数据处理的类似模块中的几个是如何出现这种情况的呢?有历史或实际原因吗? (例如,我可以想象完全省略 struct 模块,并简单地添加一个更方便的 API 来读取/写入 C 结构到 ctypes。)

最佳答案

免责声明:这篇文章是基于我对 Python stdlib 中“分工”的理解的猜测,而不是基于事实可引用的信息。

您的问题源于“C 结构”和“二进制数据”往往可以互换使用的事实,虽然在实践中是正确的,但在技术意义上是错误的。 struct 文档也具有误导性:它声称可以在“C 结构”上工作,而更好的描述是“二进制数据”,并带有一些关于 C 兼容性的免责声明。

从根本上说,structarrayctypes 做不同的事情struct 处理将 Python 值转换为内存中的二进制格式。 array 处理有效地存储大量值。 ctypes 处理 C 语言(*)。功能上的重叠源于这样一个事实,即对于 C,“内存中的二进制格式”是原生的,而“有效存储值”将它们打包到类似 C 的数组中。

您还会注意到 struct 可以让您轻松指定字节序,因为它以多种不同的方式处理二进制数据的打包和解包;而在 ctypes 中,获得非 native 字节顺序更加困难,因为它使用 C 本身的字节顺序

如果您的任务是读取二进制数据结构,则抽象级别会增加:

  1. 通过int.from_bytes等方式手动拆分字节数组并转换部分
  2. 用格式字符串描述数据并使用struct一次性解包
  3. 使用类似 Construct 的库用逻辑术语声明性地描述结构。

ctypes 在这里甚至不用考虑,因为对于这个任务,使用 ctypes 几乎是通过一种不同的编程语言。它对您的示例同样有效的事实是偶然的;它之所以有效,是因为 C 本身就适合表达多种打包二进制数据的方式。但是,如果您的结构是混合字节序的,例如,将很难在 ctypes 中表达。另一个示例是没有 C 等效项的半精度 float (参见 here )。

从这个意义上说,ctypes 使用struct 也是非常合理的——毕竟,“打包和解包二进制数据”是“与 C 接口(interface)”的子任务。

另一方面,struct 使用 ctypes 是没有意义的:这就像为字符使用 email 库编码转换,因为这是电子邮件库可以完成的任务。

(*) 嗯,基本上。更精确的说法是“基于 C 的环境”,即现代计算机如何在低级别上工作,这是由于与 C 作为主要系统语言的共同进化。

关于Python:struct 和 array 与 ctypes 中的相似功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52004279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com