PythoncTypes:将整数列表转换为短数组
我正在尝试将一个整数列表转换为一个简短的ctypes数组。然后我想将该数组分配给bigendian结构中的一个字段。我试着这样做:PythoncTypes:将整数列表转换为短数组,python,python-3.x,ctypes,endianness,Python,Python 3.x,Ctypes,Endianness,我正在尝试将一个整数列表转换为一个简短的ctypes数组。然后我想将该数组分配给bigendian结构中的一个字段。我试着这样做: from ctypes import BigEndianStructure, c_uint16 class Test(BigEndianStructure): _pack_ = 1 _fields_ = [('arr', c_uint16 * 10)] num_list = [45, 56, 23] tester = Test() short_a
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)
但它抱怨缓冲区不是一个“be_数组”,我认为这与endianness有关:
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
回溯(最近一次呼叫最后一次):
文件“test.py”,第14行,在
tester.arr=短数组。从缓冲区复制(缓冲区)
类型错误:类型不兼容,c_ushort_数组_10实例而不是c_ushort_be_数组_10实例
我是不是想得太多了?有没有人对如何解决这个问题有什么建议
编辑:根据注释的澄清,C中相应的结构有一个uint16 arr[MAX_LEN],其中MAX_LEN=10。因此,如果传递的数组不是完整的最大值,我想发送一个0填充的数组
我是不是想得太多了
是的,大量的。根本不需要从缓冲区复制或字节。如果您需要大端结构的唯一原因是您在大端系统上,那么使用常规结构将使您的生活更加轻松:
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
如果你真的想使用big-endian,即使你使用的是一个小endian系统,那么事情会变得更复杂。首先,它将导致C中的45
、56
和23
变成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
对bigendian结构的支持很少。您不能创建c\u-ushort\u-be
或c\u-ushort\u-be\u-Array\u 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)))
输出(原始结构的十六进制表示):
另请参见模块。它可能适合您的需要。为了澄清,您希望的输出是否为Cuint16\u t arr[10]={45,56,23,0,0,0,0,0,0}代码>?(当然,假设你在一个大端系统上)是的,这是正确的。C中相应的结构有一个uint16_t arr[MAX_LEN],其中MAX_LEN=10。因此,我认为如果传递的数组不是完整的MAX_LEN,它将获得一个0填充的数组。谢谢!这就是我要找的。我知道这比我现在做的要容易。它也适用于一个小的endianstructure,这是很好的了解。谢谢,你的第二个例子是我想要的更多,因为我需要的是bigendian结构,而不是原生endianness。
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'