Wie zu packen und entpacken mit ctypes (Struktur <-> str)
Frage
Dies könnte eine dumme Frage, aber ich konnte nicht eine gute Antwort in der Dokumentation oder überall.
Wenn ich verwenden struct eine binäre Struktur zu definieren, die Struktur verfügt über 2 symmetrische Verfahren zur Serialisierung und Deserialisierung (Pack und entpacken) aber es scheint, ctypes nicht über eine einfache Möglichkeit, dies zu tun. Hier ist meine Lösung, die falsch anfühlt:
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...
Lösung
The PythonInfo Wiki hat eine Lösung für dieses.
FAQ: Wie kann ich Bytes Python aus einem ctypes.Structure kopieren
def send(self): return buffer(self)[:]
FAQ: Wie kann ich kopieren Bytes in einem ctypes.Structure von Python
?def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
Ihre send
ist die (mehr oder weniger) Äquivalent pack
und receiveSome
ist eine Art von pack_into
. Wenn Sie eine „sichere“ Situation, wo Sie in einer Struktur des gleichen Typs wie das Original sind Auspacken, können Sie einzeilige es wie memmove(addressof(y), buffer(x)[:], sizeof(y))
x
in y
zu kopieren. Natürlich werden Sie wahrscheinlich eine Variable als das zweite Argument, anstatt eine wörtliche Verpackung von x
.
Andere Tipps
Haben Sie einen Blick auf diesen Link auf binäre I / O in Python:
http://www.dabeaz.com /blog/2009/08/python-binary-io-handling.html
Auf dieser Basis können Sie einfach schreiben die folgenden von einem Puffer zu lesen (und nicht nur Dateien):
g = open("foo","rb")
q = Example()
g.readinto(q)
zu schreiben ist einfach:
g.write(q)
Das gleiche gilt für über Sockets:
s.send(q)
und
s.recv_info(q)
Ich habe einige Tests mit pack / entpacken und ctypes und dieser Ansatz ist die am schnellsten mit Ausnahme gerade in C schreiben
Getestet auf Python3
e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)