Python Ctypes:将整数列表转换为短裤数组

问题描述 投票:1回答:2

我正在尝试将整数列表转换为短裤的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)

因此,我尝试扩展列表并将int转换为大端字节:

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填充的数组。

python python-3.x ctypes endianness
2个回答
1
投票

对BigEndianStructure的支持最少。您无法创建c_ushort_bec_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模块。它可能适合您的需求。


-1
投票

我是否考虑得太多?

是,很大。完全不需要弄乱from_buffer_copybytes。如果您需要使用大端结构的唯一原因是您使用的是大端系统,那么使用常规结构将使您的生活更加轻松:

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,那么事情就会变得更加复杂。首先,它将导致455623成为C中的11520143365888。如果您不希望发生这种情况,则希望以上解决方案。如果那确实是您想要的,请继续阅读。在这种情况下,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
© www.soinside.com 2019 - 2024. All rights reserved.