Как упаковать и распаковать с помощью ctypes (Structure ↔ 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...
Ответы
Ответ 1
У этой версии есть версия для PythonInfo.
FAQ: Как скопировать байты в 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
- это a pack_into
. Если у вас есть "безопасная" ситуация, когда вы распаковываете в структуру того же типа, что и оригинал, вы можете сделать однострочное выражение как memmove(addressof(y), buffer(x)[:], sizeof(y))
, чтобы скопировать x
в y
. Конечно, у вас, вероятно, будет переменная как второй аргумент, а не буквальная упаковка x
.
Ответ 2
Посмотрите эту ссылку на двоичный код ввода/вывода в 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