# 4.3 `struct` -- 文字列データをパックされたバイナリデータとして解釈する

このモジュールは、 Python の値と Python 上で文字列データとして表される C の構造体データとの間の変換を実現します。このモジュールでは、C 構造体の レイアウトおよび Python の値との間で行いたい変換をコンパクトに表現する ために、フォーマット文字列 を使います。 このモジュールは特に、ファイルに保存されたり、ネットワーク接続を経由 したバイナリデータを扱うときに使われます。

このモジュールは以下の例外と関数を定義しています:

exception `error`
  様々な状況で送出された例外です; 引数は何が問題かを記述する文字列 です。

`pack`( | fmt, v1, v2, ...)

  値 `v1, v2, ...` が与えられたフォーマット で含まれる文字列データを返します。引数は指定したフォーマットが要求する 型と正確に一致していなければなりません。

`unpack`( | fmt, string)

  (おそらく `pack(fmt, ...)` でパックされた) 文字列 データを、与えられた書式に従ってアンパックします。値が一つしかない場合を 含め、結果はタプルで返されます。文字列データにはフォーマットが要求する だけのデータが正確に含まれていなければなりません (`len(string)` が `calcsize(fmt)` と一致しなければ なりません)。

`calcsize`( | fmt)

  与えられたフォーマットに対応する構造体のサイズ (すなわち文字列データの サイズ) を返します。

フォーマット文字 (format character) は以下の意味を持っています; C と Python の間の変換では、値は正確に以下に指定された型でなくては なりません:

フォーマット | C での型 | Python | 備考
--- | --- | --- | ---
`x` | pad byte | no value |
`c` | `char` | 長さ 1 の文字列 |
`b` | `signed char` | 整数型 (integer) |
`B` | `unsigned char` | 整数型 |
`h` | `short` | 整数型 |
`H` | `unsigned short` | 整数型 |
`i` | `int` | 整数型 |
`I` | `unsigned int` | long 整数型 |
`l` | `long` | 整数型 |
`L` | `unsigned long` | long 整数型 |
`q` | `long long` | long 整数型 | (1)
`Q` | `unsigned long long` | long 整数型 | (1)
`f` | `float` | 浮動小数点型 |
`d` | `double` | 浮動小数点型 |
`s` | `char[]` | 文字列 |
`p` | `char[]` | 文字列 |
`P` | `void *` | 整数型 |

注意事項:

(1)
  フォーマット文字 "`q`" および "`Q`" は、 プラットフォームの C コンパイラが C の `long long` 型、 Windows では `__int64` をサポートする場合にのみ、 プラットフォームネイティブの値との変換を行うモードだけで利用することが できます。

  バージョン2.2 以降で新規追加された 仕様です。

フォーマット文字の前に整数をつけ、繰り返し回数 (count) を指定することが できます。 例えば、フォーマット文字列 `'4h'` は `'hhhh'` と全く同じ 意味です。

フォーマット文字間の空白文字は無視されます; count とフォーマット 文字の間にはスペースを入れてはいけません。

フォーマット文字 "`s`" では、count は文字列のサイズと して扱われます。他のフォーマット文字のように繰り返し回数ではありません; 例えば、`'10c'` が 10 個のキャラクタを表すのに対して、 `'10s'` は 10 バイトの長さを持った 1 個 の文字列です。文字列をパックする際には、 指定した長さにフィットするように、必要に応じて切り詰められたりヌル文字 で穴埋めされたりします。また特殊なケースとして、(`'0c'` が 0 個の キャラクタを表すのに対して) `'0s'` は 1 個の空文字列を意味します。

フォーマット文字 "`p`" は "Pascal 文字列 (pascal string)" をコードします。Pascal 文字列は固定長のバイト列に収められた短い可変長の 文字列です。count は実際に文字列データ中に収められる全体の長さ です。このデータの先頭の 1 バイトには文字列の長さか255 のうち、小さい 方の数が収められます。その後に文字列のバイトデータが続きます。 `pack()` に渡された Pascal 文字列の長さが長すぎた (count-1 よりも長い) 場合、先頭の count-1 バイトが書き込まれます。文字列が count-1 よりも短い場合、指定した count バイトに達するまでの残りの 部分はヌルで埋められます。`unpack()` では、フォーマット文字 "`p`" は指定された count バイトだけデータを読み込みますが、 返される文字列は決して 255 文字を超えることはないので注意してください。

フォーマット文字 "`I`"、 "`L`"、 "`q`" および "`Q`" では、返される値は Python long 整数です。

フォーマット文字 "`P`" では、返される値は Python 整数型または long 整数型で、これはポインタの値を Python での整数にキャストする際に、 値を保持するために必要なサイズに依存します。 `NULL` ポインタは常に Python 整数型の `0` になります。 ポインタ型のサイズを持った値をパックする際には、Python 整数型 および long 整数型オブジェクトを使うことができます。例えば、 Alpha および Merced プロセッサは 64 bit のポインタ値を使いますが、これは ポインタを保持するために Python long 整数型が使われることを意味します; 32 bit ポインタを使う他のプラットフォームでは Python 整数型が使われ ます。

デフォルトでは、C では数値はマシンのネイティブ (native) の形式 およびバイトオーダ (byte order) で表され、適切にアラインメント (alignment) するために、必要に応じて数バイトのパディングを行ってスキップします (これは C コンパイラが用いるルールに従います)。

これに代わって、フォーマット文字列の最初の文字を使って、バイトオーダや サイズ、アラインメントを指定することができます。指定できる文字を 以下のテーブルに示します:

文字 | バイトオーダ | サイズおよびアラインメント
--- | --- | ---
`@` | ネイティブ | ネイティブ
`=` | ネイティブ | 標準
`<` | リトルエンディアン | 標準
`>` | ビッグエンディアン | 標準
`!` | ネットワークバイトオーダ (= ビッグエンディアン) | 標準

フォーマット文字列の最初の文字が上のいずれかでない場合、"`@`" であるとみなされます。

ネイティブのバイトオーダはビッグエンディアンかリトルエンディアンで、 ホスト計算機に依存します。例えば、Motorola および Sun のプロセッサは ビッグエンディアンです; Intel および DEC のプロセッサはリトルエンディアン です。

ネイティブのサイズおよびアラインメントは C コンパイラの `sizeof` 式で決定されます。ネイティブのサイズおよびアラインメントは大抵ネイティブ のバイトオーダと同時に使われます。

標準のサイズおよびアラインメントは以下のようになります: どの型に対しても、 アラインメントは必要ありません (ので、パディングを使う必要があります); `short` は 2 バイトです; `int` と `long` は 4 バイトです; `long long` (Windows では `__int64`) は 8 バイトです; `float` と `double` は順に 32-bit あるいは 64-bit の IEEE 浮動小数点数です。

"`@`" と "`=`" の違いに注意してください: 両方とも ネイティブのバイトオーダですが、後者のバイトサイズやバイトオーダは 標準のものに合わせてあります。

"`!`" 表記法はネットワークバイトオーダがビッグエンディアンか リトルエンディアンか忘れちゃったという熱意に乏しい人向けに用意されて います。

バイトオーダに関して、「(強制的にバイトスワップを行う)ネイティブの逆」 を指定する方法はありません; "`<`" または "`>`" のうち ふさわしい方を選んでください。

"`P`" フォーマット文字はネイティブバイトオーダでのみ利用可能 です (デフォルトのネットワークバイトオーダに設定するか、"`@`" バイトオーダ指定文字を指定しなければなりません)。 "`=`" を指定 した場合、ホスト計算機のバイトオーダに基づいてリトルエンディアンと ビッグエンディアンのどちらを使うかを決めます。struct モジュールはこの 設定をネイティブのオーダ設定として解釈しないので、"`P`" を 使うことはできません。

以下に例を示します (この例は全てビッグエンディアンのマシンで、 ネイティブのバイトオーダ、サイズおよびアラインメントの場合です):

    >>> from struct import *
    >>> pack('hhl', 1, 2, 3)
    '\x00\x01\x00\x02\x00\x00\x00\x03'
    >>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
    (1, 2, 3)
    >>> calcsize('hhl')
    8

ヒント: 特定の型によるアラインメント要求に従うように構造体の末端を そろえるには、count をゼロにした特定の型でフォーマットを終端します。 例えば、フォーマット `'llh0l'` は、 long 型が 4 バイトを境界と してそろえられていると仮定して、末端に 2 バイトをパディングします。 この機能は変換対象がネイティブのサイズおよびアラインメントの場合 にのみ働きます; 標準に型サイズおよびアラインメントの設定ではいかなる アラインメントも行いません。

参考資料:

`array`モジュール:
  一様なデータ型からなるバイナリ記録データのパック.

`xdrlib`モジュール:
  XDR データのパックおよびアンパック。.