I want to access ctype.Structure with I have defined, as a bytes in Python (b''
).
I don't know it is a correct way? I need to send a header (it should be architecture free) to other device.
So I defined it for example as:
class Header(ctypes.Structure):
_pack_ = 2
_fields_ = [
('version', c_uint8),
('additional_options', c_uint8),
('soft_version', c_uint16),
('compilation_time', c_uint8 * 6),
('crc', c_uint16)
]
Now I need to calculate CRC. Start from filed at version
to compilation_time
I have a function that work with bytes.
So for me it would be OK just convert ctypes.Structure to bytes (b'') or access directly memory and change last two bytes.
I have tried use struct but I didn't found pragma option.
struct
is what you want:
import struct
from binascii import crc32
fmt = struct.Struct('<BBH6s')
data = struct.pack('<BBH6s', 1, 2, 3, b'170207')
print(data)
print(data.hex(' '))
crc = 0xABCD # <do your calculation here>
data += struct.pack('<H',crc)
print(data)
print(data.hex(' '))
<
means pack little-endian and will not add padding bytes like C would, so no _pack_
is necessary. If you need big-endian, use >
instead.
I used 6s
and passed a byte string of the correct length for your time. If you want to pass raw bytes instead use 6B
and list the 6 bytes instead of the one string.
Output:
b'\x01\x02\x03\x00170207'
01 02 03 00 31 37 30 32 30 37
b'\x01\x02\x03\x00170207\xcd\xab'
01 02 03 00 31 37 30 32 30 37 cd ab
Here is a ctypes
solution. I used crc32
because one was available in the library for demo purposes.
import ctypes as ct
from binascii import crc32
class Header(ct.LittleEndianStructure):
_pack_ = 1 # prevent alignment padding
_fields_ = (('version', ct.c_uint8),
('additional_options', ct.c_uint8),
('soft_version', ct.c_uint16),
('compilation_time', ct.c_uint8 * 6),
('crc', ct.c_uint32))
h = Header(1, 2, 3)
h.compilation_time[:] = b'ABCDEF' # use slicing to copy into an array
b = bytes(h)[:Header.crc.offset] # convert struct to bytes and truncate CRC
print(b)
h.crc = crc32(b) # Set the correct CRC
b = bytes(h) # convert whole struct to bytes
print(b)
print(b.hex(' '))
Output:
b'\x01\x02\x03\x00ABCDEF'
b'\x01\x02\x03\x00ABCDEF\xe7s\x85\xa6'
01 02 03 00 41 42 43 44 45 46 e7 73 85 a6