繁体   English   中英

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

对 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)))

Output(原始结构的十六进制表示):

b'002d003800170000000000000000000000000000'

另见结构模块。 它可能适合您的需求。

这是我想太多了吗?

是的,大量。 根本不需要弄乱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,即使您使用的是 little-endian 系统,那么事情就会变得更加复杂。 首先,它会导致 C 中的455623变为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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM