ctypesを使用してパックおよびアンパックする方法(構造<-> str)
質問
これはばかげた質問かもしれませんが、ドキュメントやどこでも良い答えが見つかりませんでした。
struct を使用してバイナリ構造を定義する場合、構造にはシリアル化と逆シリアル化の2つの対称メソッド(パックとアンパック)がありますが、 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...
解決
PythonInfo wiki にはこれに対する解決策があります。
FAQ:ctypes.StructureからPythonにバイトをコピーするにはどうすればよいですか
def send(self): return buffer(self)[:]
FAQ:Pythonからctypes.Structureにバイトをコピーするにはどうすればよいですか?
def receiveSome(self, bytes): fit = min(len(bytes), ctypes.sizeof(self)) ctypes.memmove(ctypes.addressof(self), bytes, fit)
Their send
は(多かれ少なかれ) pack
に相当し、 receiveSome
は pack_into
。 「安全」がある場合元と同じ型の構造体に展開する状況では、 memmove(addressof(y)、buffer(x)[:]、sizeof(y))
x
を y
にコピーします。もちろん、おそらく x
のリテラルパッキングではなく、2番目の引数として変数があります。
他のヒント
PythonのバイナリI / Oに関する次のリンクをご覧ください:
http://www.dabeaz.com /blog/2009/08/python-binary-io-handling.html
これに基づいて、(ファイルだけでなく)バッファから読み取るために次のように書くことができます:
g = open("foo","rb")
q = Example()
g.readinto(q)
書くことは単純です:
g.write(q)
ソケットを使用する場合も同じ:
s.send(q)
and
s.recv_info(q)
pack / unpackおよびctypesを使用していくつかのテストを行いましたが、このアプローチはCで直接記述する以外は最速です
Python3でテスト済み
e = Example(12, 13)
serialized = bytes(e)
deserialized = Example.from_buffer_copy(serialized)