C言語の構造体を書き込んだファイルをビッグエンディアンからリトルエンディアンにPythonで変換する
Perlでも書いたんだけど、Pythonのほうが綺麗に書けたのでPythonで書いたやつを。
*1
C言語の構造体をそのまま書き込んだバイナリファイルがあるんだけど、ビッグエンディアンからリトルエンディアンに直したい。
構造体の定義はわかっているとする。
コンバートモジュール
構造体のフィールド、入力ファイル名、出力ファイル名とエンディアンのフラグを受け取って、入力ファイルから指定エンディアンのバイナリデータを読み込んで、逆で出力ファイルに書き込む。
やっていることは
- 構造体のもとになるクラスの動的定義
- そのインスタンス生成
- 入力ファイルをバイナリでオープン
- 入力の構造体に読込み
- 入力構造体から出力構造体にフィールドをコピー
- 出力ファイルをバイナリでオープン
- 室力ファイルに出力構造体を書込み
#!/usr/bin/env python3 import ctypes ## エンディアン変換 ## fields :構造体のメンバ変数定義 ## fileNameIn :入力ファイル名 ## fileNameOut :出力ファイル名 ## flg :0:ビッグエンディアン>リトルエンディアン ## 1:リトルエンディアン>ビッグエンディアン def convertEndian(fields,fileNameIn,fileNameOut,flg): intype = ctypes.LittleEndianStructure if flg else ctypes.BigEndianStructure outtype = ctypes.BigEndianStructure if flg else ctypes.LittleEndianStructure StructIn = type('StructIn', (intype,), {'_fields_':fields}) StructOut = type('StructOut', (outtype,), {'_fields_':fields}) tIn = StructIn() tOut = StructOut() with open(fileNameIn, 'rb') as f: f.readinto(tIn) for item in tIn._fields_: setattr(tOut, item[0], getattr(tIn, item[0])) with open(fileNameOut, 'wb') as f: f.write(tOut) ## リトルエンディアン→ビッグエンディアン変換 ## fields :構造体のメンバ変数定義 ## fileNameIn :入力ファイル名 ## fileNameOut :出力ファイル名 def convertLittleToBig(fields,fileNameIn,fileNameOut): "リトルエンディアン→ビッグエンディアン変換" convertEndian(fields, fileNameIn, fileNameOut, 1) ## ビッグエンディアン→リトルエンディアン変換 ## fields :構造体のメンバ変数定義 ## fileNameIn :入力ファイル名 ## fileNameOut :出力ファイル名 def convertBigToLittle(fields,fileNameIn,fileNameOut): "ビッグエンディアン→リトルエンディアン変換" convertEndian(fields, fileNameIn, fileNameOut, 0)
呼び出しサンプル
構造体のメンバ変数を定義してコンバートメソッドを呼び出す
#!/usr/bin/env python3 import ctypes from endianConvertHelp import * """ /*** C言語の構造体定義 ***/ typedef struct __TEST{ int n1; int n2; int n3; char text[16]; }TEST_STRUCT; """ ## C言語の構造体のメンバ変数を定義する fields = ( ('n1', ctypes.c_int32), ('n2', ctypes.c_int32), ('n3', ctypes.c_int32), ('text', ctypes.c_char*16), ) ## リトルエンディアン→ビッグエンディアン変換メソッド # convertLittleToBig(fields, ## メンバ定義 # 'test.dat', ## 入力ファイル名 # 'test.dat.py.big') ## 出力ファイル名 ## ビッグエンディアン→リトルエンディアン変換メソッド convertBigToLittle(fields, ## メンバ定義 'test.dat.py.big', ## 入力ファイル名 'test.dat.py.ltl') ## 出力ファイル名