Python structモジュール

Python structモジュールは、Cのstructデータ型にアクセスしたり操作したりするためのシンプルなPythonicインターフェースを提供するために使用されます。

このモジュールはPythonの値をCの構造体に変換することができ、その逆も可能です。

このモジュールはPythonの値をCの構造体に変換したり、その逆を行うことができます。Cの構造体はPythonのバイトオブジェクトとして使用されますが、これはCにはオブジェクトというものがなく、バイトサイズのデータ構造しかないからです。

Python structモジュールのメソッド

このモジュールではC言語の構造体を扱うので、このモジュールが提供する関数のいくつかを見てみましょう。

struct.pack()

これは要素をPythonのバイト文字列(バイトオブジェクト)にパックするために使用されます。

Format: struct.pack(v1,v2,v3,v4,v5,v6,v6)

Pythonのバイト文字列に要素をパックします。pack(format, v1, v2, …)

v1v2, …は、バイトオブジェクトにパックされる値です。 これらはC構造体のフィールド値を表しています。 nのフィールドを持つC構造は、正確にnの値を持たなければならないので、引数はフォーマットが要求する値と正確に一致しなければなりません。 これは、Cコードで使用されるようなバイト文字列のデータ型を指定する必要があるために必要です。 以下の表は、formatの最も一般的な値の一覧です。 データ型を指定するには、値ごとに1つのフォーマットが必要です。

td

td

フォーマット C Datatype Pythonタイプ
char a string of 長さ1
? _Bool _bool
h short integer
l long 整数
i int 整数
f float
d double float
s char string

いくつかの例を使って理解していきましょう。

以下のスニペットは、pack()を使用して、3つの整数1、2、3をバイトオブジェクトに格納しています。 私のマシンでは整数のサイズは4バイトなので、4バイトのブロックが3つ見えますが、これはC言語では3つの整数に相当します。

import struct# We pack 3 integers, so 'iii' is requiredvariable = struct.pack('iii', 1, 2, 3)print(type(variable), variable)variable_2 = struct.pack('iic', 1, 2, b'A')print('\n', variable_2)

出力

<class 'bytes'> b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'b'\x01\x00\x00\x00\x02\x00\x00\x00A'

適切な型が渡されない場合は、Pythonのstructモジュールによって例外struct.errorが発生します。

import struct# Error!! Incorrect datatype assignmentvariable = struct.pack('ccc', 1, 2, 3)print(type(variable), variable)

出力

struct.error: char format requires a bytes object of length 1

struct.unpack()

Python structモジュールのこの関数は、パックされた値を適切なフォーマットにしたがって元の表現にアンパックします。

Format: struct.unpack(format, string)

これは stringformat というフォーマット指定子に従って展開します。

これは struct.pack()unpack()を使って渡されたpythonの値を返してみましょう。

import structbyte_str = b'\x01\x00\x00\x00\x02\x00\x00\x00A'# Using the same format specifier as before, since# we want to get Python values for the same byte-stringtuple_vals = struct.unpack('iic', byte_str)print(tuple_vals)

出力

(1, 2, b'A')

確かに、ご覧の通りです。 pack()unpack()の両方に同じフォーマット指定子を使用すれば、このタプルから古いPythonの値をパックすることができます。

struct.calcsize()

この関数は、データの型を取得してサイズを計算するために、与えられたフォーマット指定子を使用して、構造体のString表現の合計サイズを返します。

Format: struct.calcsize(fmt)

import structprint('C Integer Size in Bytes:', struct.calcsize('i'))print('Size of 3 characters in Bytes:', struct.calcsize('ccc'))

Output

C Integer Size in Bytes: 4Size of 3 characters in Bytes: 3

struct.pack_into()

この関数は、ctypesモジュールで利用可能なPythonの文字列バッファに値をパックするために使用されます。

Format: struct.pack_into(fmt, buffer, offset, v1, v2, …)

ここで、fmtbufferは、指定されたパックされた値を格納する文字列バッファです。

これは値を返さず、buffer の文字列に値を格納します。

import struct import ctypes # We will create a string buffer having a size# equal to that of a struct with 'iic' values.buf_size = struct.calcsize('iic') # Create the string bufferbuff = ctypes.create_string_buffer(buf_size) # struct.pack() returns the packed data struct.pack_into('iic', buff, 0, 1, 2, b'A')print(buff)# Display the contents of the bufferprint(buff)

出力

<ctypes.c_char_Array_9 object at 0x7f4bccef1040>b'\x01\x00\x00\x00\x02\x00\x00\x00A'

つまり、バッファ文字列にパックされた値を取得しています。

struct.unpack_from()

unpack()と同様に、バッファ文字列から値を取り出すための対応策があります。

Format: struct.unpack_from(fmt, buffer, offset)

これは struct.unpack() と同様に、値のタプルを返します。

import struct import ctypes # We will create a string buffer having a size# equal to that of a struct with 'iic' values.buf_size = struct.calcsize('iic') # Create the string bufferbuff = ctypes.create_string_buffer(buf_size) # struct.pack() returns the packed data struct.pack_into('iic', buff, 0, 1, 2, b'A')print(struct.unpack_from('iic', buff, 0))

出力

(1, 2, b'A')

まとめ

本記事では、Pythonのstructモジュールを使ってC型構造体オブジェクトを扱う方法を学びました。

コメントを残す

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