ctypesを使用してパックおよびアンパックする方法(構造<-> str)

StackOverflow https://stackoverflow.com/questions/1825715

  •  22-07-2019
  •  | 
  •  

質問

これはばかげた質問かもしれませんが、ドキュメントやどこでも良い答えが見つかりませんでした。

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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top