Как упаковать и распаковать, используя ctypes (Структура < - > str)
Вопрос
Это может быть глупый вопрос, но я не смог найти хорошего ответа в документах или где-либо еще.
Если я использую struct для определения двоичной структуры, структура имеет 2 симметричных метода для сериализации и десериализации (упаковать и распаковать), но, похоже, ctypes не имеет простой способ сделать это. Вот мое решение, которое кажется неправильным:
from ctypes import *
class Example(Structure):
_fields_ = [
("index", c_int),
("counter", c_int),
]
def Pack(ctype_instance):
buf = string_at(byref(ctype_instance), sizeof(ctype_instance))
return buf
def Unpack(ctype, buf):
cstring = create_string_buffer(buf)
ctype_instance = cast(pointer(cstring), POINTER(ctype)).contents
return ctype_instance
if __name__ == "__main__":
e = Example(12, 13)
buf = Pack(e)
e2 = Unpack(Example, buf)
assert(e.index == e2.index)
assert(e.counter == e2.counter)
# note: for some reason e == e2 is False...
Решение
Вики PythonInfo имеет решение для этого.
Часто задаваемые вопросы: как скопировать байты в Python из ctypes.Structure?
def send(self): return buffer(self)[:]
FAQ: как скопировать байты в ctypes.Structure из Python?
def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
Их send
является (более или менее) эквивалентом pack
, а receiveSome
является своего рода pack_into код>. Если у вас есть «сейф» Ситуация, когда вы распаковываете в структуру того же типа, что и оригинал, вы можете однострочно, например,
memmove (addressof (y), buffer (x) [:], sizeof (y))
скопировать x
в y
. Конечно, у вас, вероятно, будет переменная в качестве второго аргумента, а не буквальная упаковка x
.
Другие советы
Посмотрите на эту ссылку на двоичном вводе / выводе в python:
http://www.dabeaz.com /blog/2009/08/python-binary-io-handling.html р>
Исходя из этого, вы можете просто написать следующее для чтения из буфера (не только файлов):
g = open("foo","rb")
q = Example()
g.readinto(q)
Написать просто:
g.write(q)
То же самое для использования сокетов:
s.send(q)
и
s.recv_info(q)
Я провел некоторое тестирование с pack / unpack и ctypes, и этот подход самый быстрый, за исключением прямой записи в C
Проверено на Python3
e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)