バッファプロトコル (buffer Protocol)
************************************

Pythonで利用可能ないくつかのオブジェクトは、下層にあるメモリ配列または
*buffer* へのアクセスを提供します。このようなオブジェクトとして、組み
込みの "bytes" や "bytearray" 、 "array.array" のようないくつかの拡張
型が挙げられます。サードバーティのライブラリは画像処理や数値解析のよう
な特別な目的のために、それら自身の型を定義することができます。

それぞれの型はそれ自身のセマンティクスを持ちますが、おそらく大きなメモ
リバッファからなるという共通の特徴を共有します。いくつかの状況では仲介
するコピーを行うことなく直接バッファにアクセスすることが望まれます。

Python は バッファプロトコル によって、C レベルと Python レベルでこの
機能を提供します。 このプロトコルには二つの側面があります。

* 提供する側では、型は「バッファインターフェース」を公開し、その型のオ
  ブジェクトが内部バッファの情報を公開できるようにします。 このインタ
  ーフェースは バッファオブジェクト構造体 (buffer object structure) で
  説明します。 Python 側については バッファ型をエミュレートする を参照
  してください。

* 利用する側には、例えばメソッドの引数として受け取ったオブジェクトの内
  部の生データへのポインタを取得する方法がいくつかあります。 Python 側
  については "memoryview" を参照してください。

"bytes" や "bytearray" などのシンプルなオブジェクトは、内部のバッファ
ーをバイト列の形式で公開します。 バイト列以外の形式も利用可能です。例
えば、 "array.array" が公開する要素はマルチバイト値になることがありま
す。

bufferインターフェースの利用者の一例は、ファイルオブジェクトの
"write()" メソッドです: bufferインターフェースを通して一連のバイト列を
提供できるどんなオブジェクトでもファイルに書き込むことができます。
"write()" は、その引数として渡されたオブジェクトの内部要素に対する読み
出し専用アクセスのみを必要としますが、 "readinto()" のような他のメソッ
ドでは、その引数の内容に対する書き込みアクセスが必要です。bufferインタ
ーフェースにより、オブジェクトは読み書き両方、読み出し専用バッファへの
アクセスを許可するかそれとも拒否するか選択することができます。

bufferインターフェースの利用者には、対象となるオブジェクトのバッファを
得る二つの方法があります:

* 正しい引数で "PyObject_GetBuffer()" を呼び出す;

* "PyArg_ParseTuple()" (またはその同族のひとつ) を "y*" 、 "w*" または
  "s*" format codes のいずれかとともに呼び出す。

どちらのケースでも、bufferが必要なくなった時に "PyBuffer_Release()" を
呼び出さなければなりません。これを怠ると、リソースリークのような様々な
問題につながる恐れがあります。

Added in version 3.12: バッファプロトコルを Python から利用できるよう
になりました。 バッファ型をエミュレートする と "memoryview" を参照して
ください。


buffer 構造体
=============

バッファ構造体（または単純に "buffers"）は別のオブジェクトのバイナリデ
ータをPythonプログラマに提供するのに便利です。これはまた、ゼロコピース
ライシング機構としても使用できます。このメモリブロックを参照する機能を
使うことで、どんなデータでもとても簡単にPythonプログラマに提供すること
ができます。メモリは、C 拡張の大きな配列定数かもしれませんし、オペレー
ティングシステムライブラリに渡す前のメモリブロックかもしれませんし、構
造化データをネイティブのインメモリ形式受け渡すのに使用されるかもしれま
せん。

Pythonインタプリタによって提供される多くのデータ型とは異なり、バッファ
は "PyObject" ポインタではなく、シンプルなC 構造体です。そのため、作成
とコピーが非常に簡単に行えます。バッファの一般的なラッパーが必要なとき
は、 memoryview オブジェクトが作成されます。

エクスポートされるオブジェクトを書く方法の短い説明には、 Buffer Object
Structures を参照してください。バッファを取得するには、
"PyObject_GetBuffer()" を参照してください。

type Py_buffer
    * 次に属します: Stable ABI (すべてのメンバーを含む) (バージョン
   3.11 より).*

   void *buf

      バッファフィールドが表している論理構造の先頭を指すポインタ。 バ
      ッファを提供するオブジェクトの下層物理メモリブロック中のどの位置
      にもなりえます。 例えば "strides" が負だと、この値はメモリブロッ
      クの末尾かもしれません。

      *連続* 配列の場合この値はメモリブロックの先頭を指します。

   PyObject *obj

      バッファを提供するオブジェクトへの新しい参照です。 この参照は利
      用側が所有し、"PyBuffer_Release()" によって自動的に解放 (参照カ
      ウントを減少) され、"NULL" に設定されます。 このフィールドは、通
      常の C API 関数の戻り値に相当します。

      "PyMemoryView_FromBuffer()" または "PyBuffer_FillInfo()" によっ
      てラップされた *一時的な* バッファである特別なケースでは、このフ
      ィールドは "NULL" です。一般的に、エクスポートオブジェクトはこの
      方式を使用してはなりません。

   Py_ssize_t len

      "product(shape) * itemsize"。contiguous配列では、下層のメモリブ
      ロックの長さになります。非contiguous 配列では、contiguous表現に
      コピーされた場合に論理構造がもつ長さです。

      "((char *)buf)[0]" から "((char *)buf)[len-1]" の範囲へのアクセ
      スは、連続性 (contiguity) を保証するリクエストによって取得された
      バッファに対してのみ許されます。 多くの場合に、そのようなリクエ
      ストは "PyBUF_SIMPLE" または "PyBUF_WRITABLE" です。

   int readonly

      バッファが読み出し専用であるか示します。このフィールドは
      "PyBUF_WRITABLE" フラグで制御できます。

   Py_ssize_t itemsize

      要素一つ分のbyte単位のサイズ。 "struct.calcsize()" を非 "NULL"
      の "format" 値に対して呼び出した結果と同じです。

      重要な例外: 利用側が "PyBUF_FORMAT" フラグなしでバッファを要求し
      た場合、"format" は "NULL" に設定されますが、"itemsize" は元の形
      式に対応する値を保持します。

      "shape" が存在する場合、 "product(shape) * itemsize == len" の等
      式が守られ、利用者は "itemsize" を buffer を読むために利用できま
      す。

      "PyBUF_SIMPLE" または "PyBUF_WRITABLE" で要求した結果、 "shape"
      が "NULL" であれば、消費者は "itemsize" を無視して "itemsize ==
      1" と見なさなければなりません。

   char *format

      単一の要素の内容を "struct" モジュール形式の構文で記述した、ヌル
      終端文字列です。 "NULL" の場合は ""B"" (符号なしバイト) とみなし
      ます。

      このフィールドは "PyBUF_FORMAT" フラグによって制御されます。

   int ndim

      メモリを n 次元配列として表すときの次元数です。 "0" の場合、
      "buf" はスカラを表す単一の要素を指します。 この場合、"shape"、
      "strides"、"suboffsets" は "NULL" でなければなりません。 次元数
      の上限は "PyBUF_MAX_NDIM" で定義されています。

   Py_ssize_t *shape

      メモリ上のN次元配列の形を示す、長さが "ndim" である "Py_ssize_t"
      の配列です。 "shape[0] * ... * shape[ndim-1] * itemsize" は
      "len" と等しくなければなりません。

      shape の値は "shape[n] >= 0" に制限されます。 "shape[n] == 0" の
      場合に特に注意が必要です。 詳細は complex arrays を参照してくだ
      さい。

      "shape" 配列は利用側にとって読み取り専用です。

   Py_ssize_t *strides

      各次元において新しい値を得るためにスキップするバイト数を示す、長
      さ "ndim" の "Py_ssize_t" の配列。

      ストライドの値は任意の整数です。 通常の配列ではストライドは一般
      に正ですが、利用側は "strides[n] <= 0" の場合も扱えなければなり
      ません。 詳細は complex arrays を参照してください。

      消費者にとって、この strides 配列は読み出し専用です。

   Py_ssize_t *suboffsets

      "Py_ssize_t" 型の要素を持つ長さ "ndim" の配列。 "suboffsets[n]
      >= 0" の場合は、 n 番目の次元に沿って保存されている値はポインタ
      で、 suboffset 値は各ポインタの参照を解決した後に何バイト加えれ
      ばいいかを示しています。 suboffset の値が負の数の場合は、ポイン
      タの参照解決は不要 (連続したメモリブロック内に直接配置されいる)
      ということになります。

      全ての suboffset が負数の場合 (つまり参照解決が不要) な場合、こ
      のフィールドは "NULL" (デフォルト値) でなければなりません。

      この種の配列表現は Python Imaging Library (PIL) で使われています
      。 このような配列で要素にアクセスする方法についてさらに詳しこと
      は complex arrays を参照してください。

      消費者にとって、suboffsets 配列は読み出し専用です。

   void *internal

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

定数。

PyBUF_MAX_NDIM
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   メモリを表す次元数の上限です。 バッファの提供側はこの上限を守らなけ
   ればなりません。 多次元バッファの利用側は "PyBUF_MAX_NDIM" 次元まで
   扱えるべきです。 現在は 64 に設定されています。


バッファリクエストのタイプ
==========================

バッファは通常、 "PyObject_GetBuffer()" を使うことで、エクスポートする
オブジェクトにバッファリクエストを送ることで得られます。メモリの論理的
な構造の複雑性は多岐にわたるため、消費者は *flags* 引数を使って、自身
が扱えるバッファの種類を指定します。

"Py_buffer" の全フィールドは、リクエストの種類によって曖昧さを残さずに
定義されます。


リクエストに依存しないフィールド
--------------------------------

下記のフィールドは *flags* の影響を受けずに、常に正しい値で設定されま
す。: "obj", "buf", "len", "itemsize", "ndim".


readonly, format
----------------

   PyBUF_WRITABLE
       * 次に属します: Stable ABI (バージョン 3.11 より).*

      "readonly" フィールドを制御します。 設定されている場合、提供側は
      書き込み可能なバッファを提供するか、失敗を報告しなければなりませ
      ん。 設定されていない場合は、読み取り専用でも書き込み可能でも構
      いませんが、すべての利用側に対して一貫した選択をする必要がありま
      す。 例えば PyBUF_SIMPLE | PyBUF_WRITABLE で、単純な書き込み可能
      バッファを要求できます。

   PyBUF_WRITEABLE

      "PyBUF_WRITABLE" の別名です。

      バージョン 3.13 で ソフト非推奨 <Soft deprecated>.

   PyBUF_FORMAT
       * 次に属します: Stable ABI (バージョン 3.11 より).*

      "format" フィールドを制御します。もしフラグが設定されていれば、
      このフィールドを正しく埋めなければなりません。フラグが設定されて
      いなければ、このフィールドを "NULL" に設定しなければなりません。

"PyBUF_WRITABLE" は、次の節に出てくるどのフラグとも | を取ってかまいま
せん。 "PyBUF_SIMPLE" は 0 と定義されているので、 "PyBUF_WRITABLE" は
単純な書き込み可能なバッファを要求する単独のフラグとして使えます。

"PyBUF_FORMAT" は、"PyBUF_SIMPLE" 以外のいずれかのフラグとビット OR で
組み合わせる必要があります。 "PyBUF_SIMPLE" はすでに形式 "B" (符号なし
バイト) を意味するためです。 "PyBUF_FORMAT" を単独で使うことはできませ
ん。


shape, strides, suboffsets
--------------------------

このフラグは、以下で複雑性が大きい順に並べたメモリの論理的な構造を制御
します。個々のフラグは、それより下に記載されたフラグのすべてのビットを
含むことに注意してください。

These values are available when compiling for the Stable ABI since
version 3.11.

+---------------------------+---------------------------+---------------------------+---------------------------+
| リクエスト                | shape                     | strides                   | suboffsets                |
|===========================|===========================|===========================|===========================|
| PyBUF_INDIRECT            | yes                       | yes                       | 必要な場合                |
+---------------------------+---------------------------+---------------------------+---------------------------+
| PyBUF_STRIDES             | yes                       | yes                       | NULL                      |
+---------------------------+---------------------------+---------------------------+---------------------------+
| PyBUF_ND                  | yes                       | NULL                      | NULL                      |
+---------------------------+---------------------------+---------------------------+---------------------------+
| PyBUF_SIMPLE              | NULL                      | NULL                      | NULL                      |
+---------------------------+---------------------------+---------------------------+---------------------------+


隣接性のリクエスト
------------------

C スタイルまたは Fortran スタイルの *連続性* は、ストライド情報の有無
にかかわらず明示的に要求できます。 ストライド情報がない場合、バッファ
は C スタイルで連続していなければなりません。

These values are available when compiling for the Stable ABI since
version 3.11.

+----------------------+----------------------+----------------------+----------------------+----------------------+
| リクエスト           | shape                | strides              | suboffsets           | contig               |
|======================|======================|======================|======================|======================|
| PyBUF_C_CONTIGUOUS   | yes                  | yes                  | NULL                 | C                    |
+----------------------+----------------------+----------------------+----------------------+----------------------+
| PyBUF_F_CONTIGUOUS   | yes                  | yes                  | NULL                 | F                    |
+----------------------+----------------------+----------------------+----------------------+----------------------+
| PyBUF_ANY_CONTIGUOUS | yes                  | yes                  | NULL                 | C か F               |
+----------------------+----------------------+----------------------+----------------------+----------------------+
| "PyBUF_ND"           | yes                  | NULL                 | NULL                 | C                    |
+----------------------+----------------------+----------------------+----------------------+----------------------+


複合リクエスト
--------------

有り得る全てのリクエストの値は、前の節でのフラグの組み合わせで網羅的に
定義されています。 便利なように、バッファープロトコルでは頻繁に使用さ
れる組み合わせを単一のフラグとして提供してます。

次のテーブルの *U* は連続性が未定義であることを表します。 利用者は
"PyBuffer_IsContiguous()" を呼び出して連続性を判定する必要があるでしょ
う。

These values are available when compiling for the Stable ABI since
version 3.11.

+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| リクエスト     | shape          | strides        | suboffsets     | contig         | readonly       | format         |
|================|================|================|================|================|================|================|
| PyBUF_FULL     | yes            | yes            | 必要な場合     | U              | 0              | yes            |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_FULL_RO  | yes            | yes            | 必要な場合     | U              | 1 か 0         | yes            |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_RECORDS  | yes            | yes            | NULL           | U              | 0              | yes            |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_RECORDS  | yes            | yes            | NULL           | U              | 1 か 0         | yes            |
| _RO            |                |                |                |                |                |                |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_STRIDED  | yes            | yes            | NULL           | U              | 0              | NULL           |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_STRIDED  | yes            | yes            | NULL           | U              | 1 か 0         | NULL           |
| _RO            |                |                |                |                |                |                |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_CONTIG   | yes            | NULL           | NULL           | C              | 0              | NULL           |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+
| PyBUF_CONTIG_  | yes            | NULL           | NULL           | C              | 1 か 0         | NULL           |
| RO             |                |                |                |                |                |                |
+----------------+----------------+----------------+----------------+----------------+----------------+----------------+


複雑な配列
==========


NumPy スタイル: shape, strides
------------------------------

NumPy スタイルの配列の論理的構造は "itemsize", "ndim", "shape",
"strides" で定義されます。

"ndim == 0" の場合は、 "buf" が指すメモリの場所は、サイズが "itemsize"
のスカラ値として解釈されます。 この場合、 "shape" と "strides" の両方
とも "NULL" です。

"strides" が "NULL" の場合は、配列は標準の n 次元 C 配列として解釈され
ます。 そうでない場合は、利用者は次のように n 次元配列にアクセスしなけ
ればなりません:

   ptr = (char *)buf + indices[0] * strides[0] + ... + indices[n-1] * strides[n-1];
   item = *((typeof(item) *)ptr);

上記のように、 "buf" はメモリブロック内のどの場所でも指すことが可能で
す。エクスポーターはこの関数を使用することによってバッファの妥当性を確
認出来ます。

   def verify_structure(memlen, itemsize, ndim, shape, strides, offset):
       """引数が、割り当てたメモリの範囲内の有効な配列を
          表しているかどうかを検証する:
              char *mem: 物理メモリブロックの先頭
              memlen: 物理メモリブロックの長さ
              offset: (char *)buf - mem
       """
       if offset % itemsize:
           return False
       if offset < 0 or offset+itemsize > memlen:
           return False
       if any(v % itemsize for v in strides):
           return False

       if ndim <= 0:
           return ndim == 0 and not shape and not strides
       if 0 in shape:
           return True

       imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
                  if strides[j] <= 0)
       imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
                  if strides[j] > 0)

       return 0 <= offset+imin and offset+imax+itemsize <= memlen


PIL スタイル: shape, strides, suboffsets
----------------------------------------

PIL スタイルの配列では通常の要素の他に、ある次元の上で次の要素を取得す
るために辿るポインタを持てます。 例えば、通常の3次元 C 配列 "char
v[2][2][3]" は、2次元配列への 2 つのポインタからなる配列 "char
(*v[2])[2][3]" と見ることもできます。 suboffset 表現では、これらの 2
つのポインタは "buf" の先頭に埋め込め、メモリのどこにでも配置できる 2
つの "char x[2][3]" 配列を指します。

次の例は、 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;
   }


バッファ関連の関数
==================

int PyObject_CheckBuffer(PyObject *obj)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   *obj* がbuffer インターフェースをサポートしている場合は "1" を返し
   、そうでない場合は "0" を返します。 "1" を返したとしても、
   "PyObject_GetBuffer()" が成功することは保証されません。 この関数は
   常に成功します。

int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   *exporter* に *flags* で指定された方法で *view* を埋めるように要求
   します。もし exporter が指定されたとおりにバッファを提供できない場
   合、 "BufferError" を送出し、 "view->obj" を "NULL" に設定した上で
   、 "-1" を返さなければなりません。

   成功した場合は "view" に情報を設定し、"view->obj" を "exporter" へ
   の新しい参照にして 0 を返します。 複数のバッファ提供側が連鎖し、要
   求を一つのオブジェクトに転送する場合は、"view->obj" が "exporter"
   の代わりにそのオブジェクトを参照しても構いません (バッファオブジェ
   クト構造体 を参照)。

   "malloc()" と "free()" のように、呼び出しに成功した
   "PyObject_GetBuffer()" と対になる "PyBuffer_Release()" の呼び出しが
   なけれなればなりません。 従って、バッファの利用が済んだら
   "PyBuffer_Release()" が厳密に1回だけ呼び出されなければなりません。

void PyBuffer_Release(Py_buffer *view)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   バッファ "view" を解放し、ビューを支えるオブジェクト "view->obj" へ
   の *強参照* も解放します (つまり参照カウントを減らします)。 バッフ
   ァを使わなくなったときは必ず呼び出してください。 呼び出さないと参照
   がリークする可能性があります。

   "PyObject_GetBuffer()" を通して取得していないバッファに対してこの関
   数を呼び出すのは間違いです。

Py_ssize_t PyBuffer_SizeFromFormat(const char *format)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   "format" が表す "itemsize" を返します。 エラーの場合は例外を送出し
   、-1 を返します。

   Added in version 3.9.

int PyBuffer_IsContiguous(const Py_buffer *view, char order)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   *view* で定義されているメモリが、 C スタイル (*order* == "'C'") の
   ときか、 Fortran スタイル (*order* == "'F'") *連続* のときか、その
   いずれか (*order* == "'A'") であれば "1" を返します。 それ以外の場
   合は "0" を返します。 この関数は常に成功します。

void *PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   与えられた *view* 内にある *indices* が指すメモリ領域を取得します。
   *indices* は "view->ndim" 個のインデックスからなる配列を指していな
   ければなりません。

int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   "buf" の連続した "len" バイトを "view" にコピーします。 "order" は
   "'C'"、"'F'"、"'A'" のいずれかで、それぞれ C スタイル、Fortran スタ
   イル、どちらでもよいことを表します。 成功した場合は "0" を返し、エ
   ラーの場合は "-1" を返します。

int PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char order)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   "src" の "len" バイトを、"buf" 内の連続した表現にコピーします。
   "order" は "'C'"、"'F'"、"'A'" のいずれかで、それぞれ C スタイル、
   Fortran スタイル、どちらでもよいことを表します。 成功した場合は "0"
   を返し、エラーの場合は "-1" を返します。

   *len* != *src->len* の場合、この関数は失敗します。

int PyObject_CopyData(PyObject *dest, PyObject *src)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   "src" から "dest" バッファにデータをコピーします。 C スタイルと
   Fortran スタイルのバッファ間で変換できます。

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

void PyBuffer_FillContiguousStrides(int ndims, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, char order)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   指定された形状と要素あたりのバイト数を持つ *連続した* 配列の、バイ
   ト単位のストライドを "strides" 配列に設定します。 "order" が "'C'"
   なら C スタイル、"'F'" なら Fortran スタイルです。

int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter, void *buf, Py_ssize_t len, int readonly, int flags)
    * 次に属します: Stable ABI (バージョン 3.11 より).*

   サイズが *len* の *buf* を *readonly* に従った書き込み可/不可の設定
   で公開するバッファリクエストを処理します。 *buf* は符号無しバイトの
   列として解釈されます。

   "flags" 引数は要求の種類を示します。 "buf" が読み取り専用なのに
   "flags" に "PyBUF_WRITABLE" が設定されている場合を除き、この関数は
   常に "flags" の指定どおりに "view" に情報を設定します。

   成功した場合は "view->obj" を "exporter" への新しい参照に設定し、0
   を返します。 それ以外の場合は "BufferError" を送出し、"view->obj"
   を "NULL" に設定して "-1" を返します。

   この関数を getbufferproc の一部として使う場合には、 *exporter* はエ
   クスポートするオブジェクトに設定しなければならず、さらに *flags* は
   変更せずに渡さなければなりません。 そうでない場合は、 *exporter* は
   "NULL" でなければなりません。
