Python Ctypes:将整数列表转换为短裤数组
Python Ctypes: convert list of integers to array of shorts
我正在尝试将整数列表转换为短裤的 ctypes 数组。然后我想将该数组分配给 BigEndianStructure 中的一个字段。我试过这样做:
from ctypes import BigEndianStructure, c_uint16
class Test(BigEndianStructure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
short_array = c_uint16 * 10
tester.arr = short_array.from_buffer_copy(bytes(num_list))
但它不喜欢列表比预期的要小:
Traceback (most recent call last):
File "test.py", line 10, in <module>
tester.arr = short_array.from_buffer_copy(bytes(num_list))
ValueError: Buffer size too small (3 instead of at least 20 bytes)
然后我尝试扩展列表并将整数转换为大端字节:
new_list = num_list[:10] + [0]*(10-len(num_list))
buffer = b''
for item in new_list:
buffer += item.to_bytes(2, byteorder='big')
tester.arr = short_array.from_buffer_copy(buffer)
但它抱怨缓冲区不是 "be_array",我假设这与字节顺序有关:
Traceback (most recent call last):
File "test.py", line 14, in <module>
tester.arr = short_array.from_buffer_copy(buffer)
TypeError: incompatible types, c_ushort_Array_10 instance instead of c_ushort_be_Array_10 instance
我是不是想多了?有人对如何解决这个问题有任何建议吗?
编辑:根据评论说明,C 中相应的结构有一个 uint16_t arr[MAX_LEN],其中 MAX_LEN=10。所以如果传递的数组不是完整的 MAX_LEN.
,我想发送一个 0 填充的数组
Am I overthinking this?
是的,大量。根本没有必要乱用 from_buffer_copy
或 bytes
。如果您需要大端结构的唯一原因是您在大端系统上,那么使用常规结构将使您的生活更轻松:
from ctypes import Structure, c_uint16
class Test(Structure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
short_array = c_uint16 * 10
tester.arr = short_array(*num_list) # Or num_list[:10] if it might be too long
如果你真的想使用大端,即使你在小端系统上,那么事情会变得更复杂。首先,它会导致 45
、56
和 23
在 C 中变成 11520
、14336
和 5888
。如果你不希望发生这种情况,那么您需要上述解决方案。如果这确实是您想要的,请继续阅读。在这种情况下,short_array = c_uint16 * 10
对您没用,因为它具有原生字节序,但您需要放入结构中的数组必须是大字节序。我不知道有什么方法可以让大端数组的类型一次全部生成,因此您需要手动填充它,如下所示:
from ctypes import BigEndianStructure, c_uint16
class Test(BigEndianStructure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
for i, x in enumerate(num_list): # Or num_list[:10] if it might be too long
tester.arr[i] = x
对 BigEndianStructure 的支持最少。您不能创建 c_ushort_be
或 c_ushort_be_Array_10
,但如果您的列表比您的数组短,您可以分配给字符串切片并且它会做正确的事情:
from ctypes import *
from binascii import hexlify
class Test(BigEndianStructure):
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
tester.arr[:len(num_list)] = num_list
print(hexlify(bytes(tester)))
输出(原始结构的十六进制表示):
b'002d003800170000000000000000000000000000'
另请参阅 struct 模块。它可能适合您的需求。
我正在尝试将整数列表转换为短裤的 ctypes 数组。然后我想将该数组分配给 BigEndianStructure 中的一个字段。我试过这样做:
from ctypes import BigEndianStructure, c_uint16
class Test(BigEndianStructure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
short_array = c_uint16 * 10
tester.arr = short_array.from_buffer_copy(bytes(num_list))
但它不喜欢列表比预期的要小:
Traceback (most recent call last):
File "test.py", line 10, in <module>
tester.arr = short_array.from_buffer_copy(bytes(num_list))
ValueError: Buffer size too small (3 instead of at least 20 bytes)
然后我尝试扩展列表并将整数转换为大端字节:
new_list = num_list[:10] + [0]*(10-len(num_list))
buffer = b''
for item in new_list:
buffer += item.to_bytes(2, byteorder='big')
tester.arr = short_array.from_buffer_copy(buffer)
但它抱怨缓冲区不是 "be_array",我假设这与字节顺序有关:
Traceback (most recent call last):
File "test.py", line 14, in <module>
tester.arr = short_array.from_buffer_copy(buffer)
TypeError: incompatible types, c_ushort_Array_10 instance instead of c_ushort_be_Array_10 instance
我是不是想多了?有人对如何解决这个问题有任何建议吗?
编辑:根据评论说明,C 中相应的结构有一个 uint16_t arr[MAX_LEN],其中 MAX_LEN=10。所以如果传递的数组不是完整的 MAX_LEN.
,我想发送一个 0 填充的数组Am I overthinking this?
是的,大量。根本没有必要乱用 from_buffer_copy
或 bytes
。如果您需要大端结构的唯一原因是您在大端系统上,那么使用常规结构将使您的生活更轻松:
from ctypes import Structure, c_uint16
class Test(Structure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
short_array = c_uint16 * 10
tester.arr = short_array(*num_list) # Or num_list[:10] if it might be too long
如果你真的想使用大端,即使你在小端系统上,那么事情会变得更复杂。首先,它会导致 45
、56
和 23
在 C 中变成 11520
、14336
和 5888
。如果你不希望发生这种情况,那么您需要上述解决方案。如果这确实是您想要的,请继续阅读。在这种情况下,short_array = c_uint16 * 10
对您没用,因为它具有原生字节序,但您需要放入结构中的数组必须是大字节序。我不知道有什么方法可以让大端数组的类型一次全部生成,因此您需要手动填充它,如下所示:
from ctypes import BigEndianStructure, c_uint16
class Test(BigEndianStructure):
_pack_ = 1
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
for i, x in enumerate(num_list): # Or num_list[:10] if it might be too long
tester.arr[i] = x
对 BigEndianStructure 的支持最少。您不能创建 c_ushort_be
或 c_ushort_be_Array_10
,但如果您的列表比您的数组短,您可以分配给字符串切片并且它会做正确的事情:
from ctypes import *
from binascii import hexlify
class Test(BigEndianStructure):
_fields_ = [('arr', c_uint16 * 10)]
num_list = [45, 56, 23]
tester = Test()
tester.arr[:len(num_list)] = num_list
print(hexlify(bytes(tester)))
输出(原始结构的十六进制表示):
b'002d003800170000000000000000000000000000'
另请参阅 struct 模块。它可能适合您的需求。