I'm trying to convert a list of integers to a ctypes array of shorts. I want to then assign that array to a field in a BigEndianStructure. I tried doing this:
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))
But it didn't like that the list was smaller than what it expected:
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)
So then I tried to extend the list and convert the ints to big endian 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)
But it complains about the buffer not being a "be_array" which I'm assuming has to do with the 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
Am I overthinking this? Does anyone have any suggestions on how to get around this?
Edit: clarification from the comments, the corresponding structure in C has a uint16_t arr[MAX_LEN], where MAX_LEN=10. So I want to send a 0 filled array if the passed array is not the full MAX_LEN.
There is minimal support for a BigEndianStructure. You can't create a c_ushort_be
or c_ushort_be_Array_10
but you can assign to a string slice if your list is shorter than your array and it will do the right thing:
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 (hexadecimal representation of raw structure):
b'002d003800170000000000000000000000000000'
See also the struct module. It might suit your needs.