Python3 ctypes 将指针复制到 ctypes.structure
Python3 ctypes copy pointer to ctypes.structure
linux 内核的 ioctl 将结构放入结构中。我正在尝试弄清楚如何对 ctypes 执行相同的操作。
我从 ioctl 收到 ParentRq。我想要一种将数据从 Message.data 复制到另一个结构(例如 EventID)的通用方法。
from ctypes import Structure, c_uint8, c_uint16, POINTER
class EventID(Structure):
_pack_ = 1
_fields_ = [
('recent_addition_timestamp', c_uint8 * 4),
('last_recid', c_uint8 * 2),
('last_sw_processed_id', c_uint8 * 2),
('last_processed_id', c_uint8 * 2),
]
_eventid_sampledata = [0x88, 0x29, 0xfd, 0x60, 0x3c, 0x02, 0xff, 0xff, 0x3c, 0x02]
class Message(Structure):
_pack_ = 1
_fields_ = [
('data_len', c_uint16),
('data', POINTER(c_uint8))
]
class ParentRq(Structure):
_pack_ = 1
_fields_ = [
('msg', Message)
]
p = ParentRq()
p.msg.data_len = len(EventID._eventid_sampledata)
p.msg.data = (c_uint8 * p.msg.data_len)(*EventID._eventid_sampledata)
# Proof that items got copied into the pointer correctly.
items = []
for i in range(p.msg.data_len):
items.append(hex(p.msg.data[i]))
# items -> ['0x88', '0x29', '0xfd', '0x60', '0x3c', '0x2', '0xff', '0xff', '0x3c', '0x2']
# Copy p.msg.data into EventID
# How do I copy p.msg.data into EventID?
eid = EventID()
清单[Python.Docs]: ctypes - A foreign function library for Python.
有多种方法可以实现,一种是使用 memmove:
>>> import ctypes as ct
>>>
>>>
>>> class EventID(ct.Structure):
... _pack_ = 1
... _fields_ = [
... ("recent_addition_timestamp", ct.c_uint8 * 4),
... ("last_recid", ct.c_uint8 * 2),
... ("last_sw_processed_id", ct.c_uint8 * 2),
... ("last_processed_id", ct.c_uint8 * 2),
... ]
...
>>>
>>> l = [0x88, 0x29, 0xfd, 0x60, 0x3c, 0x02, 0xff, 0xff, 0x3c, 0x02]
>>> size = len(l)
>>> arr = (ct.c_ubyte * size)(*l)
>>> ptr = ct.cast(arr, ct.POINTER(ct.c_ubyte)) # The equivalent of Message.data (ParentRq.msg.data) instance
[hex(ptr[i]) for i in range(size)]
>>> ['0x88', '0x29', '0xfd', '0x60', '0x3c', '0x2', '0xff', '0xff', '0x3c', '0x2']
>>>
>>> eid = EventID() # Initialize members to default values (0)
>>>
>>> for f, _ in EventID._fields_:
... print(f, [hex(i) for i in getattr(eid, f)[:]])
...
recent_addition_timestamp ['0x0', '0x0', '0x0', '0x0']
last_recid ['0x0', '0x0']
last_sw_processed_id ['0x0', '0x0']
last_processed_id ['0x0', '0x0']
>>>
>>> ct.memmove(ct.addressof(eid), ptr, size)
2361449631368
>>>
>>> for f, _ in EventID._fields_:
... print(f, [hex(i) for i in getattr(eid, f)[:]])
...
recent_addition_timestamp ['0x88', '0x29', '0xfd', '0x60']
last_recid ['0x3c', '0x2']
last_sw_processed_id ['0xff', '0xff']
last_processed_id ['0x3c', '0x2']
linux 内核的 ioctl 将结构放入结构中。我正在尝试弄清楚如何对 ctypes 执行相同的操作。
我从 ioctl 收到 ParentRq。我想要一种将数据从 Message.data 复制到另一个结构(例如 EventID)的通用方法。
from ctypes import Structure, c_uint8, c_uint16, POINTER
class EventID(Structure):
_pack_ = 1
_fields_ = [
('recent_addition_timestamp', c_uint8 * 4),
('last_recid', c_uint8 * 2),
('last_sw_processed_id', c_uint8 * 2),
('last_processed_id', c_uint8 * 2),
]
_eventid_sampledata = [0x88, 0x29, 0xfd, 0x60, 0x3c, 0x02, 0xff, 0xff, 0x3c, 0x02]
class Message(Structure):
_pack_ = 1
_fields_ = [
('data_len', c_uint16),
('data', POINTER(c_uint8))
]
class ParentRq(Structure):
_pack_ = 1
_fields_ = [
('msg', Message)
]
p = ParentRq()
p.msg.data_len = len(EventID._eventid_sampledata)
p.msg.data = (c_uint8 * p.msg.data_len)(*EventID._eventid_sampledata)
# Proof that items got copied into the pointer correctly.
items = []
for i in range(p.msg.data_len):
items.append(hex(p.msg.data[i]))
# items -> ['0x88', '0x29', '0xfd', '0x60', '0x3c', '0x2', '0xff', '0xff', '0x3c', '0x2']
# Copy p.msg.data into EventID
# How do I copy p.msg.data into EventID?
eid = EventID()
清单[Python.Docs]: ctypes - A foreign function library for Python.
有多种方法可以实现,一种是使用 memmove:
>>> import ctypes as ct >>> >>> >>> class EventID(ct.Structure): ... _pack_ = 1 ... _fields_ = [ ... ("recent_addition_timestamp", ct.c_uint8 * 4), ... ("last_recid", ct.c_uint8 * 2), ... ("last_sw_processed_id", ct.c_uint8 * 2), ... ("last_processed_id", ct.c_uint8 * 2), ... ] ... >>> >>> l = [0x88, 0x29, 0xfd, 0x60, 0x3c, 0x02, 0xff, 0xff, 0x3c, 0x02] >>> size = len(l) >>> arr = (ct.c_ubyte * size)(*l) >>> ptr = ct.cast(arr, ct.POINTER(ct.c_ubyte)) # The equivalent of Message.data (ParentRq.msg.data) instance [hex(ptr[i]) for i in range(size)] >>> ['0x88', '0x29', '0xfd', '0x60', '0x3c', '0x2', '0xff', '0xff', '0x3c', '0x2'] >>> >>> eid = EventID() # Initialize members to default values (0) >>> >>> for f, _ in EventID._fields_: ... print(f, [hex(i) for i in getattr(eid, f)[:]]) ... recent_addition_timestamp ['0x0', '0x0', '0x0', '0x0'] last_recid ['0x0', '0x0'] last_sw_processed_id ['0x0', '0x0'] last_processed_id ['0x0', '0x0'] >>> >>> ct.memmove(ct.addressof(eid), ptr, size) 2361449631368 >>> >>> for f, _ in EventID._fields_: ... print(f, [hex(i) for i in getattr(eid, f)[:]]) ... recent_addition_timestamp ['0x88', '0x29', '0xfd', '0x60'] last_recid ['0x3c', '0x2'] last_sw_processed_id ['0xff', '0xff'] last_processed_id ['0x3c', '0x2']