如何使用ctypes打包和解压缩(Structure < - > str)

Mr *_*emp 41 python struct ctypes

这可能是一个愚蠢的问题,但我无法在文档或任何地方找到一个好的答案.

如果我使用struct来定义二进制结构,那么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...
Run Code Online (Sandbox Code Playgroud)

Mar*_*off 30

PythonInfo wiki有一个解决方案.

FAQ:如何从ctypes.Structure将字节复制到Python?

def send(self):
    return buffer(self)[:]
Run Code Online (Sandbox Code Playgroud)

FAQ:如何从Python复制字节到ctypes.Structure?

def receiveSome(self, bytes):
    fit = min(len(bytes), ctypes.sizeof(self))
    ctypes.memmove(ctypes.addressof(self), bytes, fit)
Run Code Online (Sandbox Code Playgroud)

它们send是(或多或少)等价的pack,并且receiveSome有点像pack_into.如果你有一个"安全"的情况,你正在解压缩到与原版相同类型的结构中,你可以将它一行化,就像 memmove(addressof(y), buffer(x)[:], sizeof(y))复制xy.当然,你可能有一个变量作为第二个参数,而不是文字包装x.

  • 在Python3中,您可以使用`bytes(self)`来提取结构字节. (7认同)

小智 18

在python中查看二进制i/o上的这个链接:

http://www.dabeaz.com/blog/2009/08/python-binary-io-handling.html

基于此,您只需编写以下内容即可从缓冲区(而不仅仅是文件)中读取:

g = open("foo","rb")
q = Example()
g.readinto(q)
Run Code Online (Sandbox Code Playgroud)

写简单就是:

g.write(q)
Run Code Online (Sandbox Code Playgroud)

使用套接字相同:

s.send(q)
Run Code Online (Sandbox Code Playgroud)

s.recv_info(q)
Run Code Online (Sandbox Code Playgroud)

我用pack/unpack和ctypes做了一些测试,这种方法是最快的,除了用C直接写

  • 在2.6+中,更通用的`pack`只是`bytearray(q)`,它也使用缓冲协议.对于泛型解包2.6也添加了,例如,`Example.from_buffer(buf)`如果`buf`是可变的,否则`Example.from_buffer_copy(buf)`. (7认同)

Tom*_*Tom 8

在 Python3 上测试

e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)
Run Code Online (Sandbox Code Playgroud)