Comment emballer et décompresser à l'aide de types (Structure < - > str)
Question
C’est peut-être une question idiote mais je n’ai pas pu trouver de bonne réponse dans les documents ou ailleurs.
Si j'utilise struct pour définir une structure binaire, la structure dispose de 2 méthodes symétriques pour la sérialisation et la désérialisation (pack et unpack), mais il semble que ctypes ne fonctionne pas. un moyen simple de le faire. Voici ma solution, qui se sent mal:
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...
La solution
Le wiki PythonInfo a une solution pour cela.
FAQ: Comment copier des octets vers Python à partir d'un ctypes.Structure?
def send(self): return buffer(self)[:]
FAQ: Comment copier des octets dans un ctypes.Structure à partir de Python?
def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
Leur send
est l'équivalent (plus ou moins) de pack
, et receiveSome
est en quelque sorte un pack_into
. Si vous avez un " coffre-fort " Lorsque vous décompressez dans une structure du même type que l'original, vous pouvez la mettre en ligne comme memmove (adressede (y), tampon (x) [:], sizeof (y))
pour copier x
dans y
. Bien sûr, vous aurez probablement une variable comme second argument, plutôt qu'un empilement littéral de x
.
Autres conseils
Regardez ce lien sur les entrées / sorties binaires en python:
http://www.dabeaz.com /blog/2009/08/python-binary-io-handling.html
Sur cette base, vous pouvez simplement écrire ce qui suit pour le lire à partir d'un tampon (pas uniquement de fichiers):
g = open("foo","rb")
q = Example()
g.readinto(q)
Écrire c'est simplement:
g.write(q)
Idem pour l'utilisation de sockets:
s.send(q)
et
s.recv_info(q)
J'ai fait quelques tests avec pack / unpack et ctypes et cette approche est la plus rapide, sauf pour écrire directement en C
Testé sur Python3
e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)