\

Pythonは非常に柔軟性の高い言語であり、C言語の構造体を扱うことも可能です。そのためのライブラリとしてctypesがあります。この記事では、Pythonとctypesを用いてC言語の構造体を扱う方法について説明します。

ctypesとは

ctypesはC言語のデータ構造をPythonで扱うことができるライブラリです。Pythonをインストールするときにこのライブラリは標準でインストールされます。Cの構造体をPythonでも扱いたいときなどに非常に便利です。

今回紹介する例としては、C側で構造体のデータをバイナリでログとして出力し、Python側でC側で吐き出されたバイナリのログデータを読み込んで表示します。PythonでCのログを解析することで2次利用(可視化や機械学習)が各段にしやすいのでマスターしたい技術です。

import ctypes
import os

class ST_DATA(ctypes.Structure):
    _pack_ = 1 # pragma pack (push, 1) と同等. これ入れないとデータがパディングされてしまう。
    _fields_ = (
        ('ID', ctypes.c_long),
        ('result', ctypes.c_short),
        ('data', ctypes.c_double*10),
    )

dataList = []

def ReadData(logFilePath:str):
    global dataList
    if os.path.exists(logFilePath):
        with open(logFilePath, 'rb') as f:
            readBytes = bytearray(f.read())
            print(f"readBytes len:  {len(readBytes)}")
            logCnt = len(readBytes) / ctypes.sizeof(ST_DATA) # 構造体データが何個存在するか算出
            print(f"logCnt:{logCnt}")
            # 読みだしたデータから各構造体のデータに分割
            for no in range(logCnt):
                bytesArr = readBytes[no*ctypes.sizeof(ST_DATA) : (no+1)*ctypes.sizeof(ST_DATA)]
                datum = ST_DATA.from_buffer(bytesArr) # binaryデータを構造体データに変換
                dataList.append(datum)
    else:
        print("log is not exist")

if __name__ == "__main__":
    filename = "log.bin" # 構造体データがいくつも書かれたバイナリファイル
    # ログデータを読み込む
    ReadData(filename)
    # データの取得方法 例
    print(dataList[0].ID) # 1番最初のログのIDを表示
    print(dataList[0].result) # 1番最初のログのresultを表示
    print(dataList[0].data[0]) # 1番最初のログのdataの1要素目を表示
    print(dataList[0].data[9]) # 1番最初のログのdataの10要素目を表示

このコードは、C言語で生成されたバイナリログをPythonで読み込み、その内容を表示するものです。C言語の構造体をPythonで扱うためには、ctypesライブラリを用いて構造体を定義します。この例では、ST_DATAという名前の構造体を定義しています。

このように、Pythonとctypesを用いることで、C言語の構造体を扱うことが可能となります。これにより、Pythonの柔軟性とC言語のパフォーマンスを組み合わせたプログラムを作成することができます。.

投稿者 admin

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です