如何使用ctypes进行打包和解包(结构体 <-> 字符串)
这可能是个傻问题,但我在文档里或者其他地方找不到好的答案。
如果我用struct来定义一个二进制结构,这个结构有两个对称的方法来进行序列化和反序列化(分别叫做打包和解包),但是ctypes似乎没有简单的方法来做到这一点。以下是我的解决方案,但我觉得这样做不太对:
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...
4 个回答
13
在Python3上进行了测试
e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)
19
你可以看看这个关于Python中二进制输入输出的链接:
http://www.dabeaz.com/blog/2009/08/python-binary-io-handling.html
根据这个链接,你可以简单地写下面的代码来从一个缓冲区读取数据(不仅仅是文件):
g = open("foo","rb")
q = Example()
g.readinto(q)
写入数据也很简单:
g.write(q)
使用套接字(socket)也是一样的:
s.send(q)
还有
s.recv_into(q)
我用pack/unpack和ctypes做了一些测试,这种方法是最快的,除了直接用C语言写的。
36
PythonInfo wiki上有这个问题的解决方案。
常见问题:我怎么把字节复制到Python中的ctypes.Structure里?
def send(self): return buffer(self)[:]
常见问题:我怎么从Python把字节复制到ctypes.Structure里?
def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
他们的 send
函数大致相当于 pack
,而 receiveSome
则有点像 pack_into
。如果你在一个“安全”的情况下,也就是说你要解包的结构体和原来的类型是一样的,你可以用一行代码像这样 memmove(addressof(y), buffer(x)[:], sizeof(y))
来把 x
复制到 y
里。当然,第二个参数你可能会用一个变量,而不是直接写 x
的值。