PythonでバイナリファイルとI/Oしたいとき「ctypes.Structure」を使用するのだが、アラインメントの調整が入るのが気に入らなかった。
ドキュメントをちゃんと見たら調整方法が書いてあったので、忘備録としてメモ。
https://docs.python.org/ja/3/library/ctypes.html#structure-union-alignment-and-byte-order
普通の使い方
こんな感じで使用します。
import ctypes
class Test1(ctypes.Structure):
_fields_ = [
("X", ctypes.c_int32),
("Y", ctypes.c_int32),
("Z", ctypes.c_int32),
]
この場合のサイズは12バイトです。
test1 = Test1()
ctypes.sizeof(test1)
12
アラインメントで調整されてしまう書き方
これだと、アラインメントでサイズが変更されます。
class Test2(ctypes.Structure):
_fields_ = [
("X", ctypes.c_int32),
("a", ctypes.c_int64),
]
この場合のサイズは16バイトです。
test2 = Test2()
ctypes.sizeof(test2)
16
なお追加される4バイトは、Xとaの間ではなく、最後に追加されるようです。(謎)
対応方法
_pack_でバイトオーダーの値を設定します。
※_fields_より前に設定すること
class Test3(ctypes.Structure):
_pack_ = 1
_fields_ = [
("X", ctypes.c_int32),
("a", ctypes.c_int64),
]
※「_pack_ = 4」でもOK
これだとサイズはちゃんと12バイトになります。
test3 = Test3()
ctypes.sizeof(test3)
12