考虑我有以下结构:
import ctypes
class MyStruct(ctypes.BigEndianStructure):
# ! These typehints are added so that the IDE recognizes the fields of the Structure
field_size1: ctypes.c_uint8
field_size7: ctypes.c_uint8
field_size8: ctypes.c_uint8
_pack_ = 1
_fields_ = [
("field_size1", ctypes.c_uint8, 1),
("field_size7", ctypes.c_uint8, 7),
("field_size8", ctypes.c_uint8, 8),
]
我能够从 Python 类型分配此结构中的位并获取我期望的字节。
s = MyStruct()
s.field_size1 = 1
s.field_size7 = 2
s.field_size8 = 3
我收到 mypy linting 错误:
Incompatible types in assignment (expression has type "int", variable has type "c_uint8") Mypy(assignment)
但是,如果我尝试使用
ctype
,程序就会崩溃(即不打印下面的消息):
s = MyStruct()
s.field_size1 = ctypes.c_uint8(1)
print("completed")
这正是我所期望的。尝试将 8 位压缩为 1 位长度是没有意义的。
在分配位域时是否有正确的方法来使用
ctypes
类型以使 Python 和 mypy 都满意而不会“类型忽略”
我能够更好地理解我的问题并得出这个答案。
这些
ctypes.Structure
对象会自动处理到本机 Python 类型的转换。
以原来的例子
>> print(type(s.field_size1))
<class 'int'>
>> s.field_size7 = -20
>> print(s.field_size7) # We also get overflow behaviour as we expect from C
206
我的困惑源于我涉及数组的实际用例,因为它们本身不会被转换。因此,当我使用原始应用程序时,我天真地将示例逻辑应用于数组和其他字段。
import ctypes
ARRAY_SIZE = 5
UINT8x5_ARRAY = ctypes.c_uint8 * ARRAY_SIZE
class MyStructWithArray(ctypes.BigEndianStructure):
_pack_ = 1
_fields_ = [
("field_size1", ctypes.c_uint8, 1),
("field_size7", ctypes.c_uint8, 7),
("field_size8x5", UINT8x5_ARRAY),
]
现在
>> s = MyStructWithArray(1,2,UINT8x5_ARRAY(*list(range(5,5+ARRAY_SIZE))))
>> print(type(s.field_size1))
<class 'int'>
>> print(type(s.field_size8x5))
<class '__main__.c_ubyte_Array_5'>
现在我需要回答的问题是如何最好地输入提示数组。
这也和元组直接赋值一样简单,并且元组可以在类型提示中具有特定的长度:
import ctypes
ARRAY_SIZE = 5
UINT8x5_ARRAY = ctypes.c_uint8 * ARRAY_SIZE
class MyStructWithArray(ctypes.BigEndianStructure):
# ! These typehints are added so that the IDE recognizes the fields of the Structure
field_size1: int
field_size7: int
field_size8x5: tuple[int, int, int, int, int]
_pack_ = 1
_fields_ = [
("field_size1", ctypes.c_uint8, 1),
("field_size7", ctypes.c_uint8, 7),
("field_size8x5", UINT8x5_ARRAY),
]
>> s.field_size8x5 = (0,1,2,3,4)
>> print(list(s.field_size8x5)) # printing is trivial as can also be casted to a native type
[0,1,2,3,4]
>> print(s.field_size8x5[6]) # mypy[misc]: Tuple index out of range