How to pack and unpack using ctypes (Structure <-> str)
ctypes, python, struct
Solution
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`.
Problem
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... ```