Как упаковать и распаковать, используя ctypes (Структура < - > str)

StackOverflow https://stackoverflow.com/questions/1825715

  •  22-07-2019
  •  | 
  •  

Вопрос

Это может быть глупый вопрос, но я не смог найти хорошего ответа в документах или где-либо еще.

Если я использую 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)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top