Pergunta

Esta poderia ser uma pergunta boba, mas eu não poderia encontrar uma boa resposta nos docs ou em qualquer lugar.

Se eu usar struct para definir uma estrutura binária, a estrutura tem 2 métodos simétricos para serialização e desserialização (embalar e desembalar), mas parece ctypes não tem uma maneira simples de fazer isso. Aqui está a minha solução, que parece errado:

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...
Foi útil?

Solução

O PythonInfo wiki tem uma solução para isso.

FAQ: Como faço para copiar bytes para Python de um ctypes.Structure

?
def send(self):
    return buffer(self)[:]

FAQ: Como faço para copiar bytes para um ctypes.Structure de Python

?
def receiveSome(self, bytes):
    fit = min(len(bytes), ctypes.sizeof(self))
    ctypes.memmove(ctypes.addressof(self), bytes, fit)

Seu send é a (mais ou menos) equivalente a pack e receiveSome é uma espécie de pack_into. Se você tem uma situação "seguro" onde você está desembalar em um struct do mesmo tipo que o original, você pode uma linha-lo como memmove(addressof(y), buffer(x)[:], sizeof(y)) a cópia x em y. Claro, você provavelmente vai ter uma variável como o segundo argumento, ao invés de uma embalagem literal de x.

Outras dicas

Tenha um olhar neste link i binário / o em python:

http://www.dabeaz.com /blog/2009/08/python-binary-io-handling.html

Com base nesta você pode simplesmente escrever o seguinte para ler de um tampão (não apenas arquivos):

g = open("foo","rb")
q = Example()
g.readinto(q)

Para escrever é simplesmente:

g.write(q)

O mesmo para o uso de soquetes:

s.send(q)

e

s.recv_info(q)

Eu fiz alguns testes com pacote / descompactar e ctypes e esta abordagem é o mais rápido, exceto para escrever diretamente no C

Testado em Python3

e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top