目次

前のトピックへ

Unicode オブジェクトと codec

次のトピックへ

タプルオブジェクト (tuple object)

このページ

バッファーオブジェクト

C で実装された Python オブジェクトは、”バッファインタフェース (buffer interface)” と呼ばれる一連の 関数を公開していることがあります。これらの関数は、あるオブジェクトのデータを生 (raw) のバイト列形式で公開するために使います。 このオブジェクトの使い手は、バッファインタフェースを使うことで、オブジェクトをあらかじめコピーしておく必要なしに、オブジェクトの データに直接アクセスできます。

バッファインタフェースをサポートするオブジェクトの例として、文字列型とアレイ (array) 型の二つがあります。文字列オブジェクトは、 その内容をバッファインタフェースのバイト単位形式で公開しています。アレイもその内容を公開していますが、注意する必要が あるのはアレイの要素は複数バイトの値になりうる、ということです。

バッファインタフェースの使い手の一例として、ファイルオブジェクトの write() メソッドがあります。バッファインタフェースを 介してバイト列を公開しているオブジェクトは全て、ファイルへの書き出しができます。オブジェクトのバッファインタフェースを操作し、 対象となるオブジェクトからデータを返させる PyArg_ParseTuple() には数多くのデータ書式化コードがあります。

バージョン 1.6 から、Python は Python レベルのバッファオブジェクトと、 C 言語レベルのバッファAPIを提供しており、任意のビルトイン型やユーザー定義型は その文字列表現を公開することができます。 しかし、両方共、幾つかの欠点のために廃止予定扱いされていて、 Python 3.0 では公式に削除され、新しい C 言語レベルのバッファAPIと 新しい Python レベルの memoryview という名前のオブジェクトに 置き換えられています。

新しいバッファAPIは Python 2.6 に逆移植されており、 memoryviews オブジェクトは Python 2.7 に逆移植されています。 古いバージョンとの互換性が必要なければ、古いAPIの代わりにこれらを使うことをおすすめします。

新スタイル Py_buffer 構造体

Py_buffer
void *buf

オブジェクトのメモリの開始位置へのポインタ

Py_ssize_t len

メモリのトータルサイズ[byte]

int readonly

バッファが読み込み専用かどうかを示す

const char *format

バッファを通してアクセスできる要素の形式を指定する、 struct モジュールスタイル文法の、 NULL 終端文字列。 このポインタの値が NULL なら、 "B" (符号無しバイト) として扱われます。

int ndim

メモリが多次元配列を表している時の次元数。 0 の場合、 stridessuboffsetsNULL でなければなりません。

Py_ssize_t *shape

メモリが多次元配列を表しているとき、その形を示す長さ ndimPy_ssize_t の配列。 ((*shape)[0] * ... * (*shape)[ndims-1])*itemsizelen と等しくなければならないことに気をつけてください。

Py_ssize_t *strides

各次元で次の要素を得るためにスキップするバイト数を示す、長さ ndimPy_ssize_t の配列。

Py_ssize_t *suboffsets

長さ ndim の、 Py_ssize_t の配列。 suboffset の各数値が0以上であるとき、その次元に格納されているのはポインタで、 suboffset の値はそのポインタの参照を解決するときに何バイトのオフセットを足すかを 示しています。 suboffset に負の数が格納されているときは、参照解決が不要であること (連続したメモリブロック内に直接配置されていること)を意味しています。

次の例は、 strides も suboffsets も非NULL の時に、N次元配列からN次元インデックスで 示される要素のポインタを返す関数です。

void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,
    Py_ssize_t *suboffsets, Py_ssize_t *indices) {
    char *pointer = (char*)buf;
    int i;
    for (i = 0; i < ndim; i++) {
        pointer += strides[i] * indices[i];
        if (suboffsets[i] >=0 ) {
            pointer = *((char**)pointer) + suboffsets[i];
        }
    }
    return (void*)pointer;
 }
Py_ssize_t itemsize

これは共有メモリ上の各要素のbyte単位のサイズを格納する変数です。 これは PyBuffer_SizeFromFormat() を使って計算できる値なので 技術的には不要なのですが、バッファを提供する側はフォーマット文字列を 解析しなくてもこの情報を知っているでしょうし、バッファを受け取る側に とっては正しく解釈するのに必要な情報です。なので、要素サイズを格納する ほうが便利ですし高速です。

void *internal

バッファを提供する側のオブジェクトが内部的に利用するための変数です。 例えば、提供側はこの変数に整数型をキャストして、 shape, strides, suboffsets といった配列をバッファを開放するときに同時に開放するべきかどうかを 管理するフラグに使うことができるでしょう。 バッファを受け取る側は、この値を変更してはなりません。

バッファ関連関数

int PyObject_CheckBuffer(PyObject *obj)

Return 1 if obj supports the buffer interface otherwise 0.

int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)

objPy_buffer view へエクスポートします。 これらの引数は NULL であってはなりません。 flag 引数は呼び出し側がどんなバッファを扱おうとしているのか、 バッファ提供側がどんなバッファを返すことが許されているのかを示す、 ビットフィールドです。 バッファインタフェースは複雑なメモリ共有を可能にしていますが、呼び出し元は すべての複雑なバッファを扱えるとは限らず、バッファ提供側がシンプルなビューを 提供できるならそれを利用したいとかもしれません。

バッファ提供側はすべての方法でメモリを共有できるとは限らず、呼び出し側に 何かが不可能であることを伝えるためにエラーを発生させる必要があるかもしれません。 その場合のエラーは、もしその問題を実際に引き起こしているのが別のエラーだったとしても、 BufferError でなければなりません。 バッファ提供側は flag の情報を使って Py_buffer 構造体のどのフィールドへの 非デフォルト値の設定を省略したり、要求されたシンプルな view を提供できない場合は エラーを発生させたりすることができます。

成功したら 0 が、エラー時には -1 が返されます。

次のテーブルは、 flags 引数が取りうる値です。

Flag 説明
PyBUF_SIMPLE これはデフォルトの flag の状態です。 結果のバッファは書き込み可能かもしれませんし、不可能かも しれません。データのフォーマットは unsigned byte とします。 これは “スタンドアロン” のフラグ定数です。他の定数と ‘|’ する必要はありません。 提供側はこのような連続したバイト列のバッファを提供できない 場合に、エラーを発生させるかもしれません。
PyBUF_WRITABLE 結果のバッファは書込み可能でなければなりません。 書き込み不可能な場合はエラーを発生させます。
PyBUF_STRIDES この値は PyBUF_ND を含みます。 バッファは strides 情報を提供しなければなりません。 (言い換えると、 strides は NULL ではなりません。) このフラグは、呼び出し元が、要素間に隙間のある不連続な 配列を扱えるときに使われます。 strides を扱うことは、 自動的に shape も扱えることを要求されます。 提供側は stride 形式のバッファを提供できないとき(例えば、 suboffset が必要な場合)はエラーを発生させます。
PyBUF_ND バッファは shape 情報を提供しなければなりません。 メモリは C スタイルの並び (最後の次元が一番高速) だと仮定 されます。提供側はこの種類の連続バッファを提供できない場合は エラーを発生させます。このフラグが指定されていな場合は shape は NULL になります。
PyBUF_C_CONTIGUOUS PyBUF_F_CONTIGUOUS PyBUF_ANY_CONTIGUOUS これらのフラグは、返されるバッファの並びを指定します。 それぞれ、C並び(最後の次元が一番高速)、Fortran並び(最初の 次元が一番高速), そのどちらでも、を意味します。 これらのフラグは PyBUF_STRIDES を含んでおり、 strides 情報が正しく格納されていることを保証します。
PyBUF_INDIRECT このフラグは、返されるバッファが suboffsets 情報を含んで いることを示します。(suboffsets が必要無いときは NULL でも かまいません。) このフラグは、バッファ利用側が suboffsets を使って参照されている間接配列を扱えるときに利用されます。 このフラグは PyBUF_STRIDES を含みます。
PyBUF_FORMAT 返されるバッファは正しい format 情報を持っていなければ なりません。このフラグは、バッファ利用側が実際に格納されて いるデータの ‘種類’ をチェックするときに利用します。 バッファ提供側は、要求された場合は常にこの情報を提供できる べきです。 format が明示的に要求されていない場合は format は NULL ('B', unsigned byte を意味する)であるべきです。
PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE) と同じ
PyBUF_STRIDED_RO (PyBUF_STRIDES) と同じ
PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE) と同じ
PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT) と同じ
PyBUF_FULL (PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE) と同じ
PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT) と同じ
PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE) と同じ
PyBUF_CONTIG_RO (PyBUF_ND) と同じ
void PyBuffer_Release(Py_buffer *view)

view バッファを開放します。 バッファが利用されなくなったときに、そのメモリを開放できるようにこの関数を呼び出すべきです。

int PyBuffer_IsContiguous(Py_buffer *view, char fortran)

view で定義されているメモリが、(fortran == 'C' のとき) C-styleか、 (fortran == 'F' のとき) Fortran-style か、 (fortran == 'A' のとき) そのいずれかであれば 1 を返します。 それ以外の場合は 0 を返します。

void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char fortran)

strides 配列を、 itemsize の大きさの要素がバイト単位で連続した、 shape の形をした (fortran'C' なら C-style, fortran'F' なら Fortran-style の) 多次元配列として埋める。

int PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len, int readonly, int infoflags)

Fill in a buffer-info structure, view, correctly for an exporter that can only share a contiguous chunk of memory of “unsigned bytes” of the given length. Return 0 on success and -1 (with raising an error) on error. バッファ提供側が与えられた長さの “unsigned bytes” の連続した1つのメモリブロックしか 提供できないものとして、 view バッファ情報構造体を正しく埋める。 成功したら 0 を、エラー時には(例外を発生させつつ) -1 を返す。

旧スタイルバッファオブジェクト

バッファインタフェースに関するより詳しい情報は、 “バッファオブジェクト構造体” 節 ( バッファオブジェクト構造体 (buffer object structure) 節) の、 PyBufferProcs の説明のところにあります。

“バッファオブジェクト” はヘッダファイル bufferobject.h の中で定義されています (このファイルは Python.h がインクルードしています)。バッファオブジェクトは、 Python プログラミングの レベルからは文字列オブジェクトと非常によく似ているように見えます: スライス、インデクス指定、結合、その他標準の文字列操作をサポート しています。しかし、バッファオブジェクトのデータは二つのデータソース: 何らかのメモリブロックか、バッファインタフェースを公開している 別のオブジェクト、のいずれかに由来しています。

バッファオブジェクトは、他のオブジェクトのバッファインタフェースから Python プログラマにデータを公開する方法として便利です。 バッファオブジェクトはゼロコピーなスライス機構 (zero-copy slicing mechanism) としても使われます。ブロックメモリを参照するという バッファオブジェクトの機能を使うことで、任意のデータをきわめて簡単に Python プログラマに公開できます。メモリブロックは巨大でもかまいませんし、C 拡張モジュール内の定数配列でもかまいません。また、オペレーティングシステムライブラリ側に渡す前の、操作用の生のブロックメモリでもかまいませんし、 構造化されたデータをネイティブのメモリ配置形式でやりとりするためにも使えます。

PyBufferObject

この PyObject のサブタイプはバッファオブジェクトを表現します。

PyTypeObject PyBuffer_Type

Python バッファ型 (buffer type) を表現する PyTypeObject です; Python レイヤにおける buffertypes.BufferType と同じオブジェクトです。

int Py_END_OF_BUFFER

この定数は、 PyBuffer_FromObject() またはの PyBuffer_FromReadWriteObject() size パラメタに渡します。このパラメタを渡すと、 PyBufferObject は指定された offset からバッファの終わりまでを base オブジェクトとして参照します。このパラメタを使うことで、関数の呼び出し側が base オブジェクト のサイズを調べる必要がなくなります。

int PyBuffer_Check(PyObject *p)

引数が PyBuffer_Type 型のときに真を返します。

PyObject* PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Return value: New reference.

新たな読み出し専用バッファオブジェクトを返します。 base が読み出し専用バッファに必要なバッファプロトコルをサポートしていない 場合や、厳密に一つのバッファセグメントを提供していない場合には TypeError を送出し、 offset がゼロ以下の場合には ValueError を送出します。バッファオブジェクトはは base オブジェクトに対する参照を保持し、バッファオブジェクトのの内容は base オブジェクトの offset から size バイトのバッファインタフェースへの参照になります。 sizePy_END_OF_BUFFER の場合、新たに作成するバッファオブジェクトの内容は base から公開されているバッファの 末尾までにわたります。

バージョン 2.5 で変更: この関数は以前は offset, size の型に int を利用していました。 この変更により、 64bit システムを正しくサポートするには修正が必要になります。

PyObject* PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
Return value: New reference.

新たな書き込み可能バッファオブジェクトを返します。パラメタおよび例外は PyBuffer_FromObject() と同じです。 base オブジェクトが書き込み可能バッファに必要なバッファプロトコルを公開していない場合、 TypeError を送出します。

バージョン 2.5 で変更: この関数は以前は offset, size の型に int を利用していました。 この変更により、 64bit システムを正しくサポートするには修正が必要になります。

PyObject* PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
Return value: New reference.

メモリ上の指定された場所から指定されたサイズのデータを読み出せる、新たな読み出し専用バッファオブジェクトを返します。 この関数が返すバッファオブジェクトが存続する間、 ptr で与えられたメモリバッファがデアロケートされないようにするのは呼び出し側の責任です。 size がゼロ以下の場合には ValueError を送出します。 size には Py_END_OF_BUFFER を指定しては なりません ; 指定すると、 ValueError を送出します。

バージョン 2.5 で変更: この関数は以前は size の型に int を利用していました。 この変更により、 64bit システムを正しくサポートするには修正が必要になります。

PyObject* PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
Return value: New reference.

PyBuffer_FromMemory() に似ていますが、書き込み可能なバッファを返します。

バージョン 2.5 で変更: この関数は以前は size の型に int を利用していました。 この変更により、 64bit システムを正しくサポートするには修正が必要になります。

PyObject* PyBuffer_New(Py_ssize_t size)
Return value: New reference.

size バイトのメモリバッファを独自に維持する新たな書き込み可能バッファオブジェクトを返します。 size がゼロまたは正の値でない場合、 ValueError を送出します。(PyObject_AsWriteBuffer() が返すような) メモリバッファは特に整列されていないので注意して下さい。

バージョン 2.5 で変更: この関数は以前は size の型に int を利用していました。 この変更により、 64bit システムを正しくサポートするには修正が必要になります。