I have need create a ctypes struct using a pointer. Example code
class MessageDecoder:
def __init__(self, raw_data : bytes):
self.raw_data = raw_data
self.writable_raw_data = None
self.datagram = None
self.tag = None
def decode(self):
c_array = cast(self.raw_data, POINTER(c_ubyte *
len(self.raw_data)))[0]
data_pointer = pointer(c_array)
self.datagram = Datagram.from_buffer(data_pointer)
I get the c_array. I can get the pointer. However, trying to create Datagram fails. I can create one using c_array. EX: Datagram.from_buffer(c_array) Datagram looks like:
class Datagram(BigEndianStructure):
_pack_ = 1
_fields_ = [
("MagicNumber", c_uint),
("VersionMinor", c_uint16),
("VersionMajor", c_uint16),
("SequenceNumber", c_uint16),
("SeqNumberHigh", c_uint16),
("DataSize", c_uint32),
("Attribute", GenericAttribute)
]
Why?
I have need create a ctypes struct using a pointer. Example code
class MessageDecoder:
def __init__(self, raw_data : bytes):
self.raw_data = raw_data
self.writable_raw_data = None
self.datagram = None
self.tag = None
def decode(self):
c_array = cast(self.raw_data, POINTER(c_ubyte *
len(self.raw_data)))[0]
data_pointer = pointer(c_array)
self.datagram = Datagram.from_buffer(data_pointer)
I get the c_array. I can get the pointer. However, trying to create Datagram fails. I can create one using c_array. EX: Datagram.from_buffer(c_array) Datagram looks like:
class Datagram(BigEndianStructure):
_pack_ = 1
_fields_ = [
("MagicNumber", c_uint),
("VersionMinor", c_uint16),
("VersionMajor", c_uint16),
("SequenceNumber", c_uint16),
("SeqNumberHigh", c_uint16),
("DataSize", c_uint32),
("Attribute", GenericAttribute)
]
Why?
Share Improve this question asked Feb 4 at 20:02 AeroClassicsAeroClassics 1,12411 silver badges22 bronze badges 01 Answer
Reset to default 1Much of decode
is unnecessary. Use Datagram.from_buffer_copy
. Copy is needed because the raw data is immutable bytes
. If bytearray
was used, then from_buffer
could be used but then the datagram would share its internal data with the byte array.
Working example (dropped the undefined GenericAttribute
):
import ctypes as ct
import struct
class Datagram(ct.BigEndianStructure):
_pack_ = 1
_fields_ = (("MagicNumber", ct.c_uint),
("VersionMinor", ct.c_uint16),
("VersionMajor", ct.c_uint16),
("SequenceNumber", ct.c_uint16),
("SeqNumberHigh", ct.c_uint16),
("DataSize", ct.c_uint32))
def __repr__(self):
return (f'Datagram(MagicNumber={self.MagicNumber}, '
f'VersionMinor={self.VersionMinor}, '
f'VersionMajor={self.VersionMajor}, '
f'SequenceNumber={self.SequenceNumber}, '
f'SeqNumberHigh={self.SeqNumberHigh}, '
f'DataSize={self.DataSize})')
raw_data = struct.pack('>LHHHHL',1,2,3,4,5,6)
print(raw_data.hex(' '))
datagram = Datagram.from_buffer_copy(raw_data)
print(datagram)
Output:
00 00 00 01 00 02 00 03 00 04 00 05 00 00 00 06
Datagram(MagicNumber=1, VersionMinor=2, VersionMajor=3, SequenceNumber=4, SeqNumberHigh=5, DataSize=6)