This might be a silly question but I couldn't find a good answer in the docs or anywhere.
If I use struct to define a binary structure, the struct has 2 symmetrical methods for serialization and deserialization (pack and unpack) but it seems ctypes doesn't have a straightforward way to do this. Here's my solution, which feels wrong:
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...
struct.pack() struct. pack() is the function that converts a given list of values into their corresponding string representation. It requires the user to specify the format and order of the values that need to be converted.
Strings of binary representation are converted into their original form using this function. The return of struct. unpack() is always a tuple.
The module struct is used to convert the native data types of Python into string of bytes and vice versa. We don't have to install it. It's a built-in module available in Python3. The struct module is related to the C languages.
The PythonInfo wiki has a solution for this.
FAQ: How do I copy bytes to Python from a ctypes.Structure?
def send(self): return buffer(self)[:]
FAQ: How do I copy bytes to a ctypes.Structure from Python?
def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
Their send
is the (more-or-less) equivalent of pack
, and receiveSome
is sort of a pack_into
. If you have a "safe" situation where you're unpacking into a struct of the same type as the original, you can one-line it like memmove(addressof(y), buffer(x)[:], sizeof(y))
to copy x
into y
. Of course, you'll probably have a variable as the second argument, rather than a literal packing of x
.
Have a look at this link on binary i/o in python:
http://www.dabeaz.com/blog/2009/08/python-binary-io-handling.html
Based on this you can simply write the following to read from a buffer (not just files):
g = open("foo","rb") q = Example() g.readinto(q)
To write is simply:
g.write(q)
The same for using sockets:
s.send(q)
and
s.recv_into(q)
I did some testing with pack/unpack and ctypes and this approach is the fastest except for writing straight in C
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With