uctypes
– 以结构化的方式访问二进制数据 该模块实现MicroPython的“外部数据接口”。其背后的设想与CPython的 ctypes
模块相似, 但是实际的API与之不同,简化并针对小规模进行了优化。该模块的基本设想是定义数据结构布局, 其功能与C语言所允许大致相同,并使用熟悉的点语法来引用子字段。
Module ustruct
访问二进制数据结构的标准Python方法(不太适合大而复杂的结构)。
uctypes
API详解 使用import uctypes
导入uctypes
模块
再使用TAB
按键来查看uctypes
中所包含的内容:
>>> import uctypes
>>> uctypes.
__name__ ARRAY BFINT16 BFINT32
BFINT8 BFUINT16 BFUINT32 BFUINT8
BF_LEN BF_POS BIG_ENDIAN FLOAT32
FLOAT64 INT INT16 INT32
INT64 INT8 LITTLE_ENDIAN LONG
LONGLONG NATIVE PTR SHORT
UINT UINT16 UINT32 UINT64
UINT8 ULONG ULONGLONG USHORT
VOID addressof bytearray_at bytes_at
sizeof struct>>> import uhashlib
>>> uhashlib.
__name__ sha256
结构布局由“描述符”定义:一个将字段名编码为键和其他属性,以将其作为关联值访问。 目前,uctype需明确规范每个字段的偏移量。偏移量是从结构开始以字节给出。
以下为不同字段类型的编码示例:
标量类型:
"field_name": uctypes.UINT32 | 0
换言之,值为从结构起始处的字段偏移量(以字节为单位)与标量类型标识符ORed进行或运算。
递归布局:
"sub": (2, {
"b0": uctypes.UINT8 | 0,
"b1": uctypes.UINT8 | 1,
})
即:值为一个2元组,元组中第一项为偏移量,第二项为结构描述符词典(注意:递归描述符中的偏移量与其定义的结构相对)。
原始类型数组:
"arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2),
即:值为一个2元组,元组中第一项为ARRAY标记与偏移量进行或运算,第二项为数组元素的标量元素类型ORed数。
集合类型的数组:
"arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}),
即:值为一个3元组,元组中第一项为ARRAY标记与偏移量进行或运算,第二项为数组中元素的数量,第三项为元素类型的描述符。
指向原始类型的指针:
"ptr": (uctypes.PTR | 0, uctypes.UINT8),
即:值为一个2元组,元组中第一项为PTR标记与偏移量进行或运算,第二项为标量元素类型。
指向集合类型的指针:
"ptr2": (uctypes.PTR | 0, {"b": uctypes.UINT8 | 0}),
即:值为一个2元组,元组中第一项为PTR标记与偏移量进行或运算,第二项为指向的描述符类型。
位字段:
"bitf0": uctypes.BFUINT16 | 0 | 0 << uctypes.BF_POS | 8 << uctypes.BF_LEN,
即:值为包含给定位字段的标量值的类型(类型名称与标量类型相似,但是带有“BF”前缀),与包含位字段的标量值进行或运算, 并与位偏移量的值和标量值内的位字段的位长度(分别由BF_POS和BF_LEN位置转换而来)进行或运算。 位字段位置是从最低有效位开始计数,且为字段的最右位的数字(换言之,标量需右移至额外位字段,位字段位置即为右移的位数)。
在以上示例中,第一个UINT16值将在偏移量0处提取(访问硬件寄存器时,即需特定的访问大小和对齐,此细节便不容忽视), 位域的最右位是该UINT16的最低位,其长度是8位,此位将被提取—这实际上将访问UINT16的最低有效字节。
注意:位域操作与目标字节的字节顺序无关,特别地,以上示例将以低位有限和高位优先结构访问UINT16的最低有效字节。 但其取决于编号为0的最低有效位。某些目标可能在其本地ABI中使用不同编号,但 uctypes
始终使用上述规范化编号。
*class*uctypes.struct
(addr, descriptor, layout_type=NATIVE)
根据内存中的结构地址、描述符(编码为字典)和布局类型(请参见下文)实例化“外部数据结构”对象。
uctypes.LITTLE_ENDIAN
低位优先包装结构的布局类型。(包装即表示每个字段所占字节与描述符中定义的完全契合,也就是说,对其为1)。
uctypes.BIG_ENDIAN
高位优先包装结构的布局类型。
uctypes.NATIVE
本地结构的布局类型—数据的字节顺序和对齐符合MicroPython运行的系统的ABI
uctypes.sizeof
(struct)
返回以字节为单位的数据结构的大小。参数可为结构类或特定实例化结构对象(或其聚合字段)。
uctypes.addressof
(obj)
返回对象的地址。参数应为字节、字节数组或其他支持缓冲区协议(返回的即为此缓冲区的地址)。
uctypes.bytes_at
(addr, size)
在给定地址和以给定大小捕捉内存为字节对象。因为字节对象为可变的,内存实际上被复制到字节对象中,所以内存内容稍后有所更改,被创建的对象保留初始值。
uctypes.bytearray_at
(addr, size)
在给定地址和以给定大小捕捉内存为字节数组对象。与上述bytes_at()函数不同,内存是通过引用捕获的,因此其也可被写入。您将在给定内存地址访问当前值。
给定一个结构描述符和其层次类型,可在给定内存地址使用 uctypes.struct()
实例化一个特定结构实例。内存地址通常来自以下来源:
结构对象允许使用标准点记法访问单个字段: my_struct.substruct1.field1
。 若一字段为标量类型的,获取其将生成一个与字段中包含的值相对应的初始值(Python整数或浮动值)。一个标量字段也可被赋值。
若字段为一个数组,则可使用标准下标运算符 []
访问其单个元素—可被读取或赋值。
若字段为一个指针,则可使用 [0]
语法(与C *
运算符相对应,尽管 [0]
也在C中运行)来消除引用。 使用其他整数值对指针进行下标(也支持0),与C中具有相同语义。
总而言之,当需使用 [0]
运算符而非 *
时,除指针解除引用外,访问结构字段一般遵循C语法。
访问非标量字段会导致分配中间对象来表示它们。这就意味着在内存分配禁用时(例如:从中断中),应特别注意需访问的布局结构。我们建议您:
避免嵌套结构。例如,避免 mcu_registers.peripheral_a.register1
,为每个外设定义单独的布局描述符,作为 peripheral_a.register1
访问。
避免其他非标量数据,如数组。例如,使用 peripheral_a.register0
而 非 peripheral_a.register[0]
。
注意:这些建议会导致布局的可读性和简洁性下降,因此仅在预计需在无分配时访问无结构字段情况下使用 (甚至可以定义2个并行布局—一个用于常规使用,一个用于禁止内存分配时使用)。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。