1. C や C++ による Python の拡張
********************************

C プログラムの書き方を知っているなら、Python に新たな組み込みモジュー
ルを追加するのはきわめて簡単です。この新たなモジュール、拡張モジュール
(*extension module*) を使うと、Python が直接行えない二つのこと: 新しい
組み込みオブジェクトの実装、そして全ての C ライブラリ関数とシステムコ
ールに対する呼び出し、ができるようになります。

拡張モジュールをサポートするため、Python API (Application Programmer's
Interface) では一連の関数、マクロおよび変数を提供していて、Python ラン
タイムシステムのほとんどの側面へのアクセス手段を提供しています。
Python API は、ヘッダ ""Python.h"" をインクルードして C ソースに取り込
みます。

拡張モジュールのコンパイル方法は、モジュールの用途やシステムの設定方法
に依存します。詳細は後の章で説明します。

注釈:

  C 拡張のインターフェイスは CPython に固有のものであり、これによる拡
  張モジュールはほかの Python 実装では動作しません。多くの場合、C 拡張
  を書くことを避けてほかの Python 実装のために移植性を確保することは可
  能です。たとえば、あなたがしたいことが C ライブラリの関数やシステム
  コールを呼び出すことである場合、 "ctypes" あるいは cffi ライブラリの
  利用を検討すべきです。これらのモジュールは C コードとインターフェイ
  スし、C 拡張を書いてコンパイルするのに較べて Python 実装間のより高い
  移植性をもった Python コードを書かせてくれます。


1.1. 簡単な例
=============

"spam" (Monty Python ファンの好物ですね) という名の拡張モジュールを作
成することにして、C ライブラリ関数 "system()" に対する Python インター
フェイスを作成したいとします。 [1] この関数は null で終端されたキャラ
クタ文字列を引数にとり、整数を返します。この関数を以下のようにして
Python から呼び出せるようにしたいとします。

   >>> import spam
   >>> status = spam.system("ls -l")

まずは "spammodule.c" を作成するところから始めます。 (伝統として、
"spam" という名前のモジュールを作成する場合、モジュールの実装が入った
C ファイルを "spammodule.c" と呼ぶことになっています; "spammify" のよ
うに長すぎるモジュール名の場合には、単に "spammify.c" にもできます。)

このファイルの最初の 2 行は以下のようにします:

   #define PY_SSIZE_T_CLEAN
   #include <Python.h>

これで、Python API を取り込みます (必要なら、モジュールの用途に関する
説明や、著作権表示を追加します)。

注釈:

  Python は、システムによっては標準ヘッダの定義に影響するようなプリプ
  ロセッサ定義を行っているので、 "Python.h" をいずれの標準ヘッダよりも
  前にインクルード *せねばなりません* 。"Python.h" をインクルードする
  前に、常に "PY_SSIZE_T_CLEAN" を定義することが推奨されます。 このマ
  クロの解説については 拡張モジュール関数でのパラメタ展開 を参照してく
  ださい。

"Python.h" で定義されているユーザから可視のシンボルは、全て接頭辞 "Py"
または "PY" が付いています。ただし、標準ヘッダファイル内の定義は除きま
す。簡単のためと、Python 内で広範に使うことになるという理由から、
""Python.h"" はいくつかの標準ヘッダファイル: "<stdio.h>" 、
"<string.h>" 、 "<errno.h>" 、および "<stdlib.h>" をインクルードしてい
ます。後者のヘッダファイルがシステム上になければ、 ""Python.h"" が関数
"malloc()" 、 "free()" および "realloc()" を直接定義します。

次にファイルに追加する内容は、Python 式 "spam.system(string)" を評価す
る際に呼び出されることになる C 関数です (この関数を最終的にどのように
呼び出すかは、後ですぐわかります):

   static PyObject *
   spam_system(PyObject *self, PyObject *args)
   {
       const char *command;
       int sts;

       if (!PyArg_ParseTuple(args, "s", &command))
           return NULL;
       sts = system(command);
       return PyLong_FromLong(sts);
   }

ここでは、Python の引数リスト (例えば、単一の式 ""ls -l"") から C 関数
に渡す引数にそのまま変換しています。 C 関数は常に二つの引数を持ち、便
宜的に *self* および *args* と呼ばれます。

*self* 引数には、モジュールレベルの関数であればモジュールが、メソッド
にはオブジェクトインスタンスが渡されます。

*args* 引数は、引数の入った Python タプルオブジェクトへのポインタにな
ります。タプル内の各要素は、呼び出しの際の引数リストにおける各引数に対
応します。引数は Python オブジェクトです --- C 関数で引数を使って何か
を行うには、オブジェクトから C の値に変換せねばなりません。Python API
の関数 "PyArg_ParseTuple()" は引数の型をチェックし、C の値に変換します
。 "PyArg_ParseTuple()" はテンプレート文字列を使って、引数オブジェクト
の型と、変換された値を入れる C 変数の型を判別します。これについては後
で詳しく説明します。

"PyArg_ParseTuple()" は、全ての引数が正しい型を持っていて、アドレス渡
しされた各変数に各引数要素を保存したときに真 (非ゼロ) を返します。この
関数は不正な引数リストを渡すと偽 (ゼロ) を返します。後者の場合、関数は
適切な例外を送出するので、呼び出し側は (例にもあるように) すぐに
"NULL" を返すようにしてください。


1.2. 幕間小話: エラーと例外
===========================

Python インタプリタ全体を通して、一つの重要な取り決めがあります: それ
は、関数が処理に失敗した場合、例外状態をセットして、エラーを示す値 (通
常は "NULL" ポインタ) を返さねばならない、ということです。例外はインタ
プリタ内の静的なグローバル変数に保存されます; この値が "NULL" の場合、
例外は何も起きていないことになります。第二のグローバル変数には、例外の
"付属値 (associated value)" ("raise" 文の第二引数) が入ります。第三の
値には、エラーの発生源が Python コード内だった場合にスタックトレースバ
ック (stack traceback) が入ります。これらの三つの変数は、
"sys.exc_info()" の Python での結果と等価な C の変数です (Python ライ
ブラリリファレンスの "sys" モジュールに関する節を参照してください。)
エラーがどのように受け渡されるかを理解するには、これらの変数についてよ
く知っておくことが重要です。

Python API では、様々な型の例外をセットするための関数をいくつか定義し
ています。

もっともよく用いられるのは "PyErr_SetString()" です。引数は例外オブジ
ェクトと C 文字列です。例外オブジェクトは通常、
"PyExc_ZeroDivisionError" のような定義済みのオブジェクトです。 C 文字
列はエラーの原因を示し、Python 文字列オブジェクトに変換されて例外の "
付属値" に保存されます。

もう一つ有用な関数として "PyErr_SetFromErrno()" があります。この関数は
引数に例外だけをとり、付属値はグローバル変数 "errno" から構築します。
もっとも汎用的な関数は "PyErr_SetObject()" で、二つのオブジェクト、例
外と付属値を引数にとります。これら関数に渡すオブジェクトには
"Py_INCREF()" を使う必要はありません。

例外がセットされているかどうかは、 "PyErr_Occurred()" を使って非破壊的
に調べられます。この関数は現在の例外オブジェクトを返します。例外が発生
していない場合には "NULL" を返します。通常は、関数の戻り値からエラーが
発生したかを判別できるはずなので、 "PyErr_Occurred()" を呼び出す必要は
ありません。

関数 *g* を呼び出す *f* が、前者の関数の呼び出しに失敗したことを検出す
ると、 *f* 自体はエラー値 (大抵は "NULL" や "-1") を返さねばなりません
。しかし、 "PyErr_*()" 関数群のいずれかを呼び出す必要は *ありません*
--- なぜなら、 *g* がすでに呼び出しているからです。次いで *f* を呼び出
したコードもエラーを示す値を *自らを呼び出したコード* に返すことになり
ますが、同様に "PyErr_*()" は *呼び出しません* 。以下同様に続きます
--- エラーの最も詳しい原因は、最初にエラーを検出した関数がすでに報告し
ているからです。エラーが Python インタプリタのメインループに到達すると
、現在実行中の Python コードは一時停止し、 Python プログラマが指定した
例外ハンドラを探し出そうとします。

(モジュールが "PyErr_*()" 関数をもう一度呼び出して、より詳細なエラーメ
ッセージを提供するような状況があります。このような状況ではそうすべきで
す。とはいえ、一般的な規則としては、 "PyErr_*()" を何度も呼び出す必要
はなく、ともすればエラーの原因に関する情報を失う結果になりがちです: こ
れにより、ほとんどの操作が様々な理由から失敗するかもしれません)

ある関数呼び出しでの処理の失敗によってセットされた例外を無視するには、
"PyErr_Clear()" を呼び出して例外状態を明示的に消去しなくてはなりません
。エラーをインタプリタには渡したくなく、自前で (何か他の作業を行ったり
、何も起こらなかったかのように見せかけるような) エラー処理を完全に行う
場合にのみ、 "PyErr_Clear()" を呼び出すようにすべきです。

"malloc()" の呼び出し失敗は、常に例外にしなくてはなりません ---
"malloc()" (または "realloc()") を直接呼び出しているコードは、
"PyErr_NoMemory()" を呼び出して、失敗を示す値を返さねばなりません。オ
ブジェクトを生成する全ての関数 (例えば "PyLong_FromLong()") は
"PyErr_NoMemory()" の呼び出しを済ませてしまうので、この規則が関係する
のは直接 "malloc()" を呼び出すコードだけです。

また、 "PyArg_ParseTuple()" という重要な例外を除いて、整数の状態コード
を返す関数はたいてい、Unix のシステムコールと同じく、処理が成功した際
にはゼロまたは正の値を返し、失敗した場合には "-1" を返します。

最後に、エラー標示値を返す際に、(エラーが発生するまでに既に生成してし
まったオブジェクトに対して "Py_XDECREF()" や "Py_DECREF()" を呼び出し
て) ごみ処理を注意深く行ってください!

どの例外を返すかの選択は、ユーザに完全にゆだねられます。
"PyExc_ZeroDivisionError" のように、全ての組み込みの Python 例外には対
応する宣言済みの C オブジェクトがあり、直接利用できます。もちろん、例
外の選択は賢く行わねばなりません --- ファイルが開けなかったことを表す
のに "PyExc_TypeError" を使ったりはしないでください (この場合はおそら
く "PyExc_IOError" の方にすべきでしょう)。引数リストに問題がある場合に
は、 "PyArg_ParseTuple()" はたいてい "PyExc_TypeError" を送出します。
引数の値が特定の範囲を超えていたり、その他の満たすべき条件を満たさなか
った場合には、 "PyExc_ValueError" が適切です。

モジュール固有の新たな例外も定義できます。定義するには、通常はファイル
の先頭部分に静的なオブジェクト変数の宣言を行います:

   static PyObject *SpamError;

そして、モジュールの初期化関数 ("PyInit_spam()") の中で、例外オブジェ
クトを使って初期化します:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       PyObject *m;

       m = PyModule_Create(&spammodule);
       if (m == NULL)
           return NULL;

       SpamError = PyErr_NewException("spam.error", NULL, NULL);
       Py_XINCREF(SpamError);
       if (PyModule_AddObject(m, "error", SpamError) < 0) {
           Py_XDECREF(SpamError);
           Py_CLEAR(SpamError);
           Py_DECREF(m);
           return NULL;
       }

       return m;
   }

Python レベルでの例外オブジェクトの名前は "spam.error" になることに注
意してください。 "PyErr_NewException()" 関数は、 組み込み例外 で述べら
れている "Exception" クラスを基底クラスに持つ例外クラスも作成できます
("NULL" の代わりに他のクラスを渡した場合は別です)。

"SpamError" 変数は、新たに生成された例外クラスへの参照を維持することに
も注意してください; これは意図的な仕様です! 外部のコードが例外オブジェ
クトをモジュールから除去できるため、モジュールから新たに作成した例外ク
ラスが見えなくなり、 "SpamError" がぶら下がりポインタ (dangling
pointer) になってしまわないようにするために、クラスに対する参照を所有
しておかねばなりません。もし "SpamError" がぶら下がりポインタになって
しまうと、 C コードが例外を送出しようとしたときにコアダンプや意図しな
い副作用を引き起こすことがあります。

この例にある、関数の戻り値型に "PyMODINIT_FUNC" を使う方法については後
で議論します。

"PyErr_SetString()" を次のように呼び出すと、拡張モジュールで例外
"spam.error" を送出することができます:

   static PyObject *
   spam_system(PyObject *self, PyObject *args)
   {
       const char *command;
       int sts;

       if (!PyArg_ParseTuple(args, "s", &command))
           return NULL;
       sts = system(command);
       if (sts < 0) {
           PyErr_SetString(SpamError, "System command failed");
           return NULL;
       }
       return PyLong_FromLong(sts);
   }


1.3. 例に戻る
=============

先ほどの関数の例に戻ると、今度は以下の実行文を理解できるはずです:

   if (!PyArg_ParseTuple(args, "s", &command))
       return NULL;

この実行文は、 "PyArg_ParseTuple()" がセットする例外によって、引数リス
トに何らかのエラーが生じたときに "NULL" (オブジェクトへのポインタを返
すタイプの関数におけるエラー標示値) を返します。エラーでなければ、引数
として与えた文字列値はローカルな変数 "command" にコピーされています。
この操作はポインタ代入であり、ポインタが指している文字列に対して変更が
行われるとは想定されていません (従って、標準 C では、変数 "command" は
"const char* command" として適切に定義せねばなりません)。

次の文では、 "PyArg_ParseTuple()" で得た文字列を渡して Unix 関数
"system()" を呼び出しています:

   sts = system(command);

"spam.system()" は "sts" を Python オブジェクトとして返さねばなりませ
ん。これには、 "PyLong_FromLong()" を使います。

   return PyLong_FromLong(sts);

上の場合では、 "Py_BuildValue()" は整数オブジェクトを返します。(そう、
整数ですら、 Python においてはヒープ上のオブジェクトなのです! )

何ら有用な値を返さない関数 ("void" を返す関数) に対応する Python の関
数は "None" を返さねばなりません。関数に "None" を返させるには、以下の
ような慣用句を使います (この慣用句は "Py_RETURN_NONE" マクロに実装され
ています):

   Py_INCREF(Py_None);
   return Py_None;

"Py_None" は特殊な Pyhton オブジェクトである "None" に対応する C での
名前です。これまで見てきたようにほとんどのコンテキストで "エラー" を意
味する "NULL" ポインタとは違い、 "None" は純粋な Python のオブジェクト
です。


1.4. モジュールのメソッドテーブルと初期化関数
=============================================

さて、前に約束したように、 "spam_system()" を Python プログラムからど
うやって呼び出すかをこれから示します。まずは、関数名とアドレスを "メソ
ッドテーブル (method table)" に列挙する必要があります:

   static PyMethodDef SpamMethods[] = {
       ...
       {"system",  spam_system, METH_VARARGS,
        "Execute a shell command."},
       ...
       {NULL, NULL, 0, NULL}        /* Sentinel */
   };

リスト要素の三つ目のエントリ ("METH_VARARGS") に注意してください。この
エントリは、C 関数が使う呼び出し規約をインタプリタに教えるためのフラグ
です。通常この値は "METH_VARARGS" か "METH_VARARGS | METH_KEYWORDS" の
はずです; "0" は旧式の "PyArg_ParseTuple()" の変化形が使われることを意
味します。

"METH_VARARGS" だけを使う場合、C 関数は、Python レベルでの引数が
"PyArg_ParseTuple()" が受理できるタプルの形式で渡されるものと想定しな
ければなりません; この関数についての詳細は下で説明します。

関数にキーワード引数が渡されることになっているのなら、第三フィールドに
"METH_KEYWORDS" ビットをセットできます。この場合、C 関数は第三引数に
"PyObject *" を受理するようにせねばなりません。このオブジェクトは、キ
ーワード引数の辞書になります。こうした関数で引数を解釈するには、
"PyArg_ParseTupleAndKeywords()" を使ってください。

メソッドテーブルはモジュール定義の構造体から参照されていなければなりま
せん:

   static struct PyModuleDef spammodule = {
       PyModuleDef_HEAD_INIT,
       "spam",   /* name of module */
       spam_doc, /* module documentation, may be NULL */
       -1,       /* size of per-interpreter state of the module,
                    or -1 if the module keeps state in global variables. */
       SpamMethods
   };

同様に、この構造体は、モジュールの初期化関数内でインタプリタに渡さねば
なりません。初期化関数はモジュールの名前を *name* としたときに
"PyInit_name()" という名前でなければならず、モジュールファイル内で定義
されているもののうち、唯一の非 "static" 要素でなければなりません:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModule_Create(&spammodule);
   }

PyMODINIT_FUNC は関数の戻り値を "PyObject *" になるように宣言し、プラ
ットフォーム毎に必要とされる、特有のリンク宣言 (linkage declaration)
を定義すること、さらに C++ の場合には関数を "extern "C"" に宣言するこ
とに注意してください。

Python プログラムが初めて "spam" モジュールを import するときに、
"PyInit_spam()" が呼ばれます。 (以下にある Python への埋め込みに関する
コメントを参照してください。) そこからモジュールオブジェクトを返す
"PyModule_Create()" が呼ばれ、モジュール定義にあるテーブル
("PyMethodDef" 構造体の配列) に基いて新たに作られたモジュールに、組み
込み関数オブジェクトが挿入されます。 "PyModule_Create()" は作成したモ
ジュールオブジェクトへのポインタを返します。あるエラーによって異常終了
するかもしれませんし、モジュールが問題無く初期化できなかった場合には
"NULL" を返すかもしれません。 init 関数はモジュールオブジェクトを呼び
出し元に返し、それが "sys.modules" に挿入されるようにしなければなりま
せん。

Python へ埋め込むときに、 "PyImport_Inittab" テーブルに存在していても
"PyInit_spam()" 関数は自動的には呼ばれません。初期化テーブルにモジュー
ルを追加するには、 "PyImport_AppendInittab()" を使ってください。その後
にオプションでモジュールを import します:

   int
   main(int argc, char *argv[])
   {
       wchar_t *program = Py_DecodeLocale(argv[0], NULL);
       if (program == NULL) {
           fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
           exit(1);
       }

       /* Add a built-in module, before Py_Initialize */
       if (PyImport_AppendInittab("spam", PyInit_spam) == -1) {
           fprintf(stderr, "Error: could not extend in-built modules table\n");
           exit(1);
       }

       /* Pass argv[0] to the Python interpreter */
       Py_SetProgramName(program);

       /* Initialize the Python interpreter.  Required.
          If this step fails, it will be a fatal error. */
       Py_Initialize();

       /* Optionally import the module; alternatively,
          import can be deferred until the embedded script
          imports it. */
       PyObject *pmodule = PyImport_ImportModule("spam");
       if (!pmodule) {
           PyErr_Print();
           fprintf(stderr, "Error: could not import module 'spam'\n");
       }

       ...

       PyMem_RawFree(program);
       return 0;
   }

注釈:

  単一のプロセス内 (または "fork()" 後の "exec()" が介入していない状態
  ) における複数のインタプリタにおいて、 "sys.modules" からエントリを
  除去したり新たなコンパイル済みモジュールを import したりすると、拡張
  モジュールによっては問題を生じることがあります。拡張モジュールの作者
  は、内部データ構造を初期化する際にはよくよく用心すべきです。

より実質的なモジュール例は、Python ソース配布物に "Modules/xxmodule.c"
という名前で入っています。このファイルはテンプレートとしても利用できま
すし、単に例としても読めます。

注釈:

  "xmodule" は "spam" と異なり、 *多段階初期化 (multi-phase
  initialization* (Python 3.5 の新機能) を使っています。 "PyInit_spam"
  が PyModuleDef を返し、モジュールの生成は後に import 機構が行います
  。多段階初期化についての詳細は **PEP 489** を参照してください。


1.5. コンパイルとリンク
=======================

新しい拡張モジュールを使えるようになるまで、まだ二つの作業: コンパイル
と、Python システムへのリンク、が残っています。動的読み込み (dynamic
loading) を使っているのなら、作業の詳細は自分のシステムが使っている動
的読み込みの形式によって変わるかもしれません; 詳しくは、拡張モジュール
のビルドに関する章 (C および C++ 拡張のビルド 章) や、Windows における
ビルドに関係する追加情報の章 (Windows 上での C および C++ 拡張モジュー
ルのビルド 章) を参照してください。

動的読み込みを使えなかったり、モジュールを常時 Python インタプリタの一
部にしておきたい場合には、インタプリタのビルド設定を変更して再ビルドし
なければならなくなるでしょう。Unixでは、幸運なことにこの作業はとても単
純です: 単に自作のモジュールファイル (例えば "spammodule.c") を展開し
たソース配布物の "Modules/"  ディレクトリに置き、
"Modules/Setup.local" に自分のファイルを説明する以下の一行:

   spam spammodule.o

を追加して、トップレベルのディレクトリで **make** を実行して、インタプ
リタを再ビルドするだけです。 "Modules/" サブディレクトリでも **make**
を実行できますが、前もって '**make** Makefile' を実行して "Makefile"
を再ビルドしておかなければならりません。(この作業は "Setup" ファイルを
変更するたびに必要です。)

モジュールが別のライブラリとリンクされている必要がある場合、ライブラリ
も設定ファイルに列挙できます。例えば以下のようにします。

   spam spammodule.o -lX11


1.6. C から Python 関数を呼び出す
=================================

これまでは、Python からの C 関数の呼び出しに重点を置いて述べてきました
。ところでこの逆: C からの Python 関数の呼び出しもまた有用です。とりわ
け、いわゆる "コールバック" 関数をサポートするようなライブラリを作成す
る際にはこの機能が便利です。ある C インタフェースがコールバックを利用
している場合、同等の機能を提供する Python コードでは、しばしば Python
プログラマにコールバック機構を提供する必要があります; このとき実装では
、 C で書かれたコールバック関数から Python で書かれたコールパック関数
を呼び出すようにする必要があるでしょう。もちろん、他の用途も考えられま
す。

幸運なことに、Python インタプリタは簡単に再帰呼び出しでき、 Python 関
数を呼び出すための標準インタフェースもあります。 (Python パーザを特定
の入力文字を使って呼び出す方法について詳説するつもりはありません ---
この方法に興味があるなら、 Python ソースコードの "Modules/main.c" にあ
る、コマンドラインオプション "-c" の実装を見てください)

Python 関数の呼び出しは簡単です。まず、C のコードに対してコールバック
を登録しようとする Python プログラムは、何らかの方法で Python の関数オ
ブジェクトを渡さねばなりません。このために、コールバック登録関数 (また
はその他のインタフェース) を提供せねばなりません。このコールバック登録
関数が呼び出された際に、引き渡された Python 関数オブジェクトへのポイン
タをグローバル変数に --- あるいは、どこか適切な場所に --- 保存します (
関数オブジェクトを "Py_INCREF()" するようよく注意してください!)。例え
ば、以下のような関数がモジュールの一部になっていることでしょう:

   static PyObject *my_callback = NULL;

   static PyObject *
   my_set_callback(PyObject *dummy, PyObject *args)
   {
       PyObject *result = NULL;
       PyObject *temp;

       if (PyArg_ParseTuple(args, "O:set_callback", &temp)) {
           if (!PyCallable_Check(temp)) {
               PyErr_SetString(PyExc_TypeError, "parameter must be callable");
               return NULL;
           }
           Py_XINCREF(temp);         /* Add a reference to new callback */
           Py_XDECREF(my_callback);  /* Dispose of previous callback */
           my_callback = temp;       /* Remember new callback */
           /* Boilerplate to return "None" */
           Py_INCREF(Py_None);
           result = Py_None;
       }
       return result;
   }

この関数は "METH_VARARGS" フラグを使ってインタプリタに登録せねばなりま
せん; "METH_VARARGS" フラグについては、 モジュールのメソッドテーブルと
初期化関数 で説明しています。 "PyArg_ParseTuple()" 関数とその引数につ
いては、 拡張モジュール関数でのパラメタ展開 に記述しています。

"Py_XINCREF()" および "Py_XDECREF()" は、オブジェクトに対する参照カウ
ントをインクリメント/デクリメントするためのマクロで、 "NULL" ポインタ
が渡されても安全に操作できる形式です (とはいえ、上の流れでは *temp* が
"NULL" になることはありません)。これらのマクロと参照カウントについては
、 参照カウント法 で説明しています。

その後、コールバック関数を呼び出す時が来たら、C 関数
"PyObject_CallObject()" を呼び出します。この関数には二つの引数: Python
関数と Python 関数の引数リストがあり、いずれも任意の Python オブジェク
トを表すポインタ型です。引数リストは常にタプルオブジェクトでなければな
らず、その長さは引数の数になります。Python 関数を引数なしで呼び出すの
なら、 "NULL" か空のタプルを渡します; 単一の引数で関数を呼び出すのなら
、単要素 (singleton) のタプルを渡します。 "Py_BuildValue()" の書式文字
列中に、ゼロ個または一個以上の書式化コードが入った丸括弧がある場合、こ
の関数はタプルを返します。以下に例を示します:

   int arg;
   PyObject *arglist;
   PyObject *result;
   ...
   arg = 123;
   ...
   /* Time to call the callback */
   arglist = Py_BuildValue("(i)", arg);
   result = PyObject_CallObject(my_callback, arglist);
   Py_DECREF(arglist);

"PyObject_CallObject()" は Python オブジェクトへのポインタを返します:
これは Python 関数からの戻り値になります。 "PyObject_CallObject()" は
、引数に対して "参照カウント中立 (reference-count- neutral)" です。上
の例ではタプルを生成して引数リストとして提供しており、このタプルは
"PyObject_CallObject()" の呼び出し直後に "Py_DECREF()" されています。

"PyObject_CallObject()" は戻り値として "新しい" オブジェクト: 新規に作
成されたオブジェクトか、既存のオブジェクトの参照カウントをインクリメン
トしたものを返します。従って、このオブジェクトをグローバル変数に保存し
たいのでないかぎり、たとえこの戻り値に興味がなくても (むしろ、そうであ
ればなおさら!) 何がしかの方法で戻り値オブジェクトを "Py_DECREF()" しな
ければなりません。

とはいえ、戻り値を "Py_DECREF()" する前には、値が *NULL* でないかチェ
ックしておくことが重要です。もし "NULL" なら、呼び出した Python 関数は
例外を送出して終了させられています。 "PyObject_CallObject()" を呼び出
しているコード自体もまた Python から呼び出されているのであれば、今度は
C コードが自分を呼び出している Python コードにエラー標示値を返さねばな
りません。それにより、インタプリタはスタックトレースを出力したり、例外
を処理するための Python コードを呼び出したりできます。例外の送出が不可
能だったり、したくないのなら、 "PyErr_Clear()" を呼んで例外を消去して
おかねばなりません。例えば以下のようにします:

   if (result == NULL)
       return NULL; /* Pass error back */
   ...use result...
   Py_DECREF(result);

Python コールバック関数をどんなインタフェースにしたいかによっては、引
数リストを "PyObject_CallObject()" に与えなければならない場合もありま
す。あるケースでは、コールバック関数を指定したのと同じインタフェースを
介して、引数リストも渡されているかもしれません。また別のケースでは、新
しいタプルを構築して引数リストを渡さねばならないかもしれません。この場
合最も簡単なのは "Py_BuildValue()" を呼ぶやり方です。例えば、整数のイ
ベントコードを渡したければ、以下のようなコードを使うことになるでしょう
:

   PyObject *arglist;
   ...
   arglist = Py_BuildValue("(l)", eventcode);
   result = PyObject_CallObject(my_callback, arglist);
   Py_DECREF(arglist);
   if (result == NULL)
       return NULL; /* Pass error back */
   /* Here maybe use the result */
   Py_DECREF(result);

"Py_DECREF(arglist)" が呼び出しの直後、エラーチェックよりも前に置かれ
ていることに注意してください! また、厳密に言えば、このコードは完全では
ありません: "Py_BuildValue()" はメモリ不足におちいるかもしれず、チェッ
クしておくべきです。

通常の引数とキーワード引数をサポートする "PyObject_Call()" を使って、
キーワード引数を伴う関数呼び出しをすることができます。上の例と同じよう
に、 "Py_BuildValue()" を作って辞書を作ります。

   PyObject *dict;
   ...
   dict = Py_BuildValue("{s:i}", "name", val);
   result = PyObject_Call(my_callback, NULL, dict);
   Py_DECREF(dict);
   if (result == NULL)
       return NULL; /* Pass error back */
   /* Here maybe use the result */
   Py_DECREF(result);


1.7. 拡張モジュール関数でのパラメタ展開
=======================================

"PyArg_ParseTuple()" 関数は以下のように宣言されています:

   int PyArg_ParseTuple(PyObject *arg, const char *format, ...);

引数 *arg* は C 関数から Python に渡される引数リストが入ったタプルオブ
ジェクトでなければなりません。 *format* 引数は書式文字列で、 Python/C
API リファレンスマニュアルの 引数の解釈と値の構築 で解説されている書法
に従わねばなりません。残りの引数は、それぞれの変数のアドレスで、書式化
文字列から決まる型になっていなければなりません。

"PyArg_ParseTuple()" は Python 側から与えられた引数が必要な型になって
いるか調べるのに対し、 "PyArg_ParseTuple()" は呼び出しの際に渡された C
変数のアドレスが有効な値を持つか調べられないことに注意してください: こ
こで間違いを犯すと、コードがクラッシュするかもしれませんし、少なくとも
でたらめなビットをメモリに上書きしてしまいます。慎重に!

呼び出し側に提供されるオブジェクトへの参照はすべて *借用* 参照
(borrowed reference) になります; これらのオブジェクトの参照カウントを
デクリメントしてはなりません!

以下にいくつかの呼び出し例を示します:

   #define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
   #include <Python.h>

   int ok;
   int i, j;
   long k, l;
   const char *s;
   Py_ssize_t size;

   ok = PyArg_ParseTuple(args, ""); /* No arguments */
       /* Python call: f() */

   ok = PyArg_ParseTuple(args, "s", &s); /* A string */
       /* Possible Python call: f('whoops!') */

   ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* Two longs and a string */
       /* Possible Python call: f(1, 2, 'three') */

   ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
       /* A pair of ints and a string, whose size is also returned */
       /* Possible Python call: f((1, 2), 'three') */

   {
       const char *file;
       const char *mode = "r";
       int bufsize = 0;
       ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
       /* A string, and optionally another string and an integer */
       /* Possible Python calls:
          f('spam')
          f('spam', 'w')
          f('spam', 'wb', 100000) */
   }

   {
       int left, top, right, bottom, h, v;
       ok = PyArg_ParseTuple(args, "((ii)(ii))(ii)",
                &left, &top, &right, &bottom, &h, &v);
       /* A rectangle and a point */
       /* Possible Python call:
          f(((0, 0), (400, 300)), (10, 10)) */
   }

   {
       Py_complex c;
       ok = PyArg_ParseTuple(args, "D:myfunction", &c);
       /* a complex, also providing a function name for errors */
       /* Possible Python call: myfunction(1+2j) */
   }


1.8. 拡張モジュール関数のキーワードパラメタ
===========================================

"PyArg_ParseTupleAndKeywords()" は、以下のように宣言されています:

   int PyArg_ParseTupleAndKeywords(PyObject *arg, PyObject *kwdict,
                                   const char *format, char *kwlist[], ...);

*arg* と *format* パラメタは "PyArg_ParseTuple()" のものと同じです。
*kwdict* パラメタはキーワード引数の入った辞書で、 Python ランタイムシ
ステムから第三パラメタとして受け取ります。 *kwlist* パラメタは各パラメ
タを識別するための文字列からなる、 "NULL" 終端されたリストです; 各パラ
メタ名は *format* 中の型情報に対して左から右の順に照合されます。成功す
ると "PyArg_ParseTupleAndKeywords()" は真を返し、それ以外の場合には適
切な例外を送出して偽を返します。

注釈:

  キーワード引数を使っている場合、タプルは入れ子にして使えません!
  *kwlist* 内に存在しないキーワードパラメタが渡された場合、
  "TypeError" の送出を引き起こします。

以下にキーワードを使ったモジュール例を示します。これは Geoff Philbrick
(philbrick@hks.com) によるプログラム例をもとにしています:

   #define PY_SSIZE_T_CLEAN  /* Make "s#" use Py_ssize_t rather than int. */
   #include <Python.h>

   static PyObject *
   keywdarg_parrot(PyObject *self, PyObject *args, PyObject *keywds)
   {
       int voltage;
       const char *state = "a stiff";
       const char *action = "voom";
       const char *type = "Norwegian Blue";

       static char *kwlist[] = {"voltage", "state", "action", "type", NULL};

       if (!PyArg_ParseTupleAndKeywords(args, keywds, "i|sss", kwlist,
                                        &voltage, &state, &action, &type))
           return NULL;

       printf("-- This parrot wouldn't %s if you put %i Volts through it.\n",
              action, voltage);
       printf("-- Lovely plumage, the %s -- It's %s!\n", type, state);

       Py_RETURN_NONE;
   }

   static PyMethodDef keywdarg_methods[] = {
       /* The cast of the function is necessary since PyCFunction values
        * only take two PyObject* parameters, and keywdarg_parrot() takes
        * three.
        */
       {"parrot", (PyCFunction)(void(*)(void))keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
        "Print a lovely skit to standard output."},
       {NULL, NULL, 0, NULL}   /* sentinel */
   };

   static struct PyModuleDef keywdargmodule = {
       PyModuleDef_HEAD_INIT,
       "keywdarg",
       NULL,
       -1,
       keywdarg_methods
   };

   PyMODINIT_FUNC
   PyInit_keywdarg(void)
   {
       return PyModule_Create(&keywdargmodule);
   }


1.9. 任意の値を構築する
=======================

"Py_BuildValue()" は "PyArg_ParseTuple()" の対極に位置するものです。こ
の関数は以下のように定義されています:

   PyObject *Py_BuildValue(const char *format, ...);

"Py_BuildValue()" は、 "PyArg_ParseTuple()" の認識する一連の書式単位に
似た書式単位を認識します。ただし (関数への出力ではなく、入力に使われる
) 引数はポインタではなく、ただの値でなければなりません。 Python から呼
び出された C 関数が返す値として適切な、新たな Python オブジェクトを返
します。

"PyArg_ParseTuple()" とは一つ違う点があります: "PyArg_ParseTuple()" は
第一引数をタプルにする必要があります (Python の引数リストは内部的には
常にタプルとして表現されるからです) が、 "Py_BuildValue()" はタプルを
生成するとは限りません。 "Py_BuildValue()" は書式文字列中に書式単位が
二つかそれ以上入っている場合にのみタプルを構築します。書式文字列が空な
ら、 "None" を返します。きっかり一つの書式単位なら、その書式単位が記述
している何らかのオブジェクトになります。サイズが 0 や 1 のタプル返させ
たいのなら、書式文字列を丸括弧で囲います。

以下に例を示します (左に呼び出し例を、右に構築される Python 値を示しま
す):

   Py_BuildValue("")                        None
   Py_BuildValue("i", 123)                  123
   Py_BuildValue("iii", 123, 456, 789)      (123, 456, 789)
   Py_BuildValue("s", "hello")              'hello'
   Py_BuildValue("y", "hello")              b'hello'
   Py_BuildValue("ss", "hello", "world")    ('hello', 'world')
   Py_BuildValue("s#", "hello", 4)          'hell'
   Py_BuildValue("y#", "hello", 4)          b'hell'
   Py_BuildValue("()")                      ()
   Py_BuildValue("(i)", 123)                (123,)
   Py_BuildValue("(ii)", 123, 456)          (123, 456)
   Py_BuildValue("(i,i)", 123, 456)         (123, 456)
   Py_BuildValue("[i,i]", 123, 456)         [123, 456]
   Py_BuildValue("{s:i,s:i}",
                 "abc", 123, "def", 456)    {'abc': 123, 'def': 456}
   Py_BuildValue("((ii)(ii)) (ii)",
                 1, 2, 3, 4, 5, 6)          (((1, 2), (3, 4)), (5, 6))


1.10. 参照カウント法
====================

C や C++のような言語では、プログラマはヒープ上のメモリを動的に確保した
り解放したりする責任があります。こうした作業は C では関数 "malloc()"
や "free()" で行います。C++では本質的に同じ意味で演算子 "new" や
"delete" が使われます。そこで、以下の議論は C の場合に限定して行います
。

"malloc()" が確保する全てのメモリブロックは、最終的には "free()" を厳
密に一度だけ呼び出して利用可能メモリのプールに戻さねばなりません。そこ
で、適切な時に "free()" を呼び出すことが重要になります。あるメモリブロ
ックに対して、 "free()" を呼ばなかったにもかかわらずそのアドレスを忘却
してしまうと、ブロックが占有しているメモリはプログラムが終了するまで再
利用できなくなります。これはメモリリーク(*memory leak*) と呼ばれていま
す。逆に、プログラムがあるメモリブロックに対して "free()" を呼んでおき
ながら、そのブロックを使い続けようとすると、別の "malloc()" 呼び出しに
よって行われるブロックの再利用と衝突を起こします。これは解放済みメモリ
の使用 (*using freed memory*) と呼ばれます。これは初期化されていないデ
ータに対する参照と同様のよくない結果 --- コアダンプ、誤った参照、不可
解なクラッシュ --- を引き起こします。

よくあるメモリリークの原因はコード中の普通でない処理経路です。例えば、
ある関数があるメモリブロックを確保し、何らかの計算を行って、再度ブロッ
クを解放するとします。さて、関数の要求仕様を変更して、計算に対するテス
トを追加すると、エラー条件を検出し、関数の途中で処理を戻すようになるか
もしれません。この途中での終了が起きるとき、確保されたメモリブロックは
解放し忘れやすいのです。コードが後で追加された場合には特にそうです。こ
のようなメモリリークが一旦紛れ込んでしまうと、長い間検出されないままに
なることがよくあります: エラーによる関数の終了は、全ての関数呼び出しの
に対してほんのわずかな割合しか起きず、その一方でほとんどの近代的な計算
機は相当量の仮想記憶を持っているため、メモリリークが明らかになるのは、
長い間動作していたプロセスがリークを起こす関数を何度も使った場合に限ら
れるからです。従って、この種のエラーを最小限にとどめるようなコーディン
グ規約や戦略を設けて、不慮のメモリリークを避けることが重要なのです。

Python は "malloc()" や "free()" を非常によく利用するため、メモリリー
クの防止に加え、解放されたメモリの使用を防止する戦略が必要です。このた
めに選ばれたのが参照カウント法 (*reference counting*) と呼ばれる手法で
す。参照カウント法の原理は簡単です: 全てのオブジェクトにはカウンタがあ
り、オブジェクトに対する参照がどこかに保存されたらカウンタをインクリメ
ントし、オブジェクトに対する参照が削除されたらデクリメントします。カウ
ンタがゼロになったら、オブジェクトへの最後の参照が削除されたことになり
、オブジェクトは解放されます。

もう一つの戦略は自動ガベージコレクション (*automatic garbage
collection*) と呼ばれています。 (参照カウント法はガベージコレクション
戦略の一つとして挙げられることもあるので、二つを区別するために筆者は "
自動 (automatic)" を使っています。) 自動ガベージコレクションの大きな利
点は、ユーザが "free()" を明示的によばなくてよいことにあります。 (速度
やメモリの有効利用性も利点として主張されています --- が、これは確たる
事実ではありません。) C における自動ガベージコレクションの欠点は、真に
可搬性のあるガベージコレクタが存在しないということです。それに対し、参
照カウント法は可搬性のある実装ができます ("malloc()" や "free()" を利
用できるのが前提です --- C 標準はこれを保証しています)。いつの日か、十
分可搬性のあるガベージコレクタが C で使えるようになるかもしれませんが
、それまでは参照カウント法でやっていく以外にはないのです。

Python では、伝統的な参照カウント法の実装を行っている一方で、参照の循
環を検出するために働く循環参照検出機構 (cycle detector) も提供していま
す。循環参照検出機構のおかげで、直接、間接にかかわらず循環参照の生成を
気にせずにアプリケーションを構築できます; というのも、参照カウント法だ
けを使ったガベージコレクション実装にとって循環参照は弱点だからです。循
環参照は、(間接参照の場合も含めて) 相互への参照が入ったオブジェクトか
ら形成されるため、循環内のオブジェクトは各々非ゼロの参照カウントを持ち
ます。典型的な参照カウント法の実装では、たとえ循環参照を形成するオブジ
ェクトに対して他に全く参照がないとしても、循環参照内のどのオブジェクト
に属するメモリも再利用できません。

循環参照検出器は循環参照を形成しているゴミを見付け回収することできます
。 "gc" モジュールは、実行時に検出器を無効にする設定インターフェースだ
けでなく、検出器を走らせる手段 ("collect()" 関数) も提供します。 循環
参照検出器はオプションのコンポーネントだと見なされます; デフォルトでは
含まれていますが、 (Mac OS X を含む) Unix プラットフォームの
**configure** スクリプトで "--without-cycle-gc" オプションを使うことで
、ビルド時に無効化することができます。 循環参照検出器がこの方法で無効
化された場合、 "gc" は利用できなくなります。


1.10.1. Python における参照カウント法
-------------------------------------

Python には、参照カウントのインクリメントやデクリメントを処理する二つ
のマクロ、 "Py_INCREF(x)" と "Py_DECREF(x)" があります。 "Py_DECREF()"
は、参照カウントがゼロに到達した際に、オブジェクトのメモリ解放も行いま
す。柔軟性を持たせるために、 "free()" を直接呼び出しません --- その代
わりにオブジェクトの型オブジェクト (*type object*) を介します。このた
めに (他の目的もありますが)、全てのオブジェクトには自身の型オブジェク
トに対するポインタが入っています。

さて、まだ重大な疑問が残っています: いつ "Py_INCREF(x)" や
"Py_DECREF(x)" を使えばよいのでしょうか? まず、いくつかの用語説明から
始めさせてください。まず、オブジェクトは "占有 (own)" されることはあり
ません; しかし、あるオブジェクトに対する参照の所有 *own a reference*
はできます。オブジェクトの参照カウントは、そのオブジェクトが参照の所有
を受けている回数と定義されています。参照の所有者は、参照が必要なくなっ
た際に "Py_DECREF()" を呼び出す役割を担います。参照の所有権は委譲
(transfer) できます。所有参照 (owned reference) の放棄には、渡す、保存
する、 "Py_DECREF()" を呼び出す、という三つの方法があります。所有参照
を処理し忘れると、メモリリークを引き起こします。

オブジェクトに対する参照は、借用 (*borrow*) も可能です。 [2] 参照の借
用者は、 "Py_DECREF()" を呼んではなりません。借用者は、参照の所有者か
ら借用した期間を超えて参照を保持し続けてはなりません。所有者が参照を放
棄した後で借用参照を使うと、解放済みメモリを使用してしまう危険があるの
で、絶対に避けねばなりません。 [3]

参照の借用が参照の所有よりも優れている点は、コードがとりうるあらゆる処
理経路で参照を廃棄しておくよう注意しなくて済むことです --- 別の言い方
をすれば、借用参照の場合には、処理の途中で関数を終了してもメモリリーク
の危険を冒すことがない、ということです。逆に、所有よりも不利な点は、ご
くまともに見えるコードが、実際には参照の借用元で放棄されてしまった後に
その参照を使うかもしれないような微妙な状況があるということです。

"Py_INCREF()" を呼び出すと、借用参照を所有参照に変更できます。この操作
は参照の借用元の状態には影響しません --- "Py_INCREF()" は新たな所有参
照を生成し、参照の所有者が担うべき全ての責任を課します (つまり、新たな
参照の所有者は、以前の所有者と同様、参照の放棄を適切に行わねばなりませ
ん)。


1.10.2. 所有権にまつわる規則
----------------------------

オブジェクトへの参照を関数の内外に渡す場合には、オブジェクトの所有権が
参照と共に渡されるか否かが常に関数インタフェース仕様の一部となります。

オブジェクトへの参照を返すほとんどの関数は、参照とともに所有権も渡しま
す。特に、 "PyLong_FromLong()" や "Py_BuildValue()" のように、新しいオ
ブジェクトを生成する関数は全て所有権を相手に渡します。オブジェクトが実
際には新たなオブジェクトでなくても、そのオブジェクトに対する新たな参照
の所有権を得ます。例えば、 "PyLong_FromLong()" はよく使う値をキャッシ
ュしており、キャッシュされた値への参照を返すことがあります。

"PyObject_GetAttrString()" のように、あるオブジェクトから別のオブジェ
クトを抽出するような関数もまた、参照とともに所有権を委譲します。こちら
の方はやや理解しにくいかもしれません。というのはよく使われるルーチンの
いくつかが例外となっているからです: "PyTuple_GetItem()" 、
"PyList_GetItem()" 、 "PyDict_GetItem()" 、および
"PyDict_GetItemString()" は全て、タプル、リスト、または辞書から借用参
照を返します。

"PyImport_AddModule()" は、実際にはオブジェクトを生成して返すことがあ
るにもかかわらず、借用参照を返します: これが可能なのは、生成されたオブ
ジェクトに対する所有参照は "sys.modules" に保持されるからです。

オブジェクトへの参照を別の関数に渡す場合、一般的には、関数側は呼び出し
手から参照を借用します --- 参照を保存する必要があるなら、関数側は
"Py_INCREF()" を呼び出して独立した所有者になります。とはいえ、この規則
には二つの重要な例外: "PyTuple_SetItem()" と "PyList_SetItem()" があり
ます。これらの関数は、渡された引数要素に対して所有権を乗っ取り (take
over) ます --- たとえ失敗してもです! ("PyDict_SetItem()" とその仲間は
所有権を乗っ取りません --- これらはいわば "普通の" 関数です。)

Python から C 関数が呼び出される際には、C 関数は呼び出し側から引数への
参照を借用します。C 関数の呼び出し側はオブジェクトへの参照を所有してい
るので、借用参照の生存期間が保証されるのは関数が処理を返すまでです。こ
のようにして借用参照を保存したり他に渡したりしたい場合にのみ、
"Py_INCREF()" を使って所有参照にする必要があります。

Python から呼び出された C 関数が返す参照は所有参照でなければなりません
--- 所有権は関数から呼び出し側へと委譲されます。


1.10.3. 薄氷
------------

数少ない状況において、一見無害に見える借用参照の利用が問題をひきおこす
ことがあります。この問題はすべて、インタプリタが非明示的に呼び出され、
インタプリタが参照の所有者に参照を放棄させてしまう状況と関係しています
。

知っておくべきケースのうち最初の、そして最も重要なものは、リスト要素に
対する参照を借りている際に起きる、関係ないオブジェクトに対する
"Py_DECREF()" の使用です。例えば:

   void
   bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);

       PyList_SetItem(list, 1, PyLong_FromLong(0L));
       PyObject_Print(item, stdout, 0); /* BUG! */
   }

上の関数はまず、 "list[0]" への参照を借用し、次に "list[1]" を値 "0"
で置き換え、最後にさきほど借用した参照を出力しています。何も問題ないよ
うに見えますね? でもそうではないのです!

"PyList_SetItem()" の処理の流れを追跡してみましょう。リストは全ての要
素に対して参照を所有しているので、要素 1 を置き換えると、以前の要素 1
を放棄します。ここで、以前の要素 1 がユーザ定義クラスのインスタンスで
あり、さらにこのクラスが "__del__()" メソッドを定義していると仮定しま
しょう。このクラスインスタンスの参照カウントが 1 だった場合、リストが
参照を放棄すると、インスタンスの "__del__()" メソッドが呼び出されます
。

クラスは Python で書かれているので、 "__del__()" は任意の Python コー
ドを実行できます。この "__del__()" が "bug()" における "item" に何か不
正なことをしているのでしょうか? その通り! "bug()" に渡したリストが
"__del__()" メソッドから操作できるとすると、 "del list[0]" の効果を持
つような文を実行できてしまいます。もしこの操作で "list[0]" に対する最
後の参照が放棄されてしまうと、 "list[0]" に関連付けられていたメモリは
解放され、結果的に "item" は無効な値になってしまいます。

問題の原因が分かれば、解決は簡単です。一時的に参照回数を増やせばよいの
です。正しく動作するバージョンは以下のようになります:

   void
   no_bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);

       Py_INCREF(item);
       PyList_SetItem(list, 1, PyLong_FromLong(0L));
       PyObject_Print(item, stdout, 0);
       Py_DECREF(item);
   }

これは実際にあった話です。以前のバージョンの Python には、このバグの一
種が潜んでいて、 "__del__()" メソッドがどうしてうまく動かないのかを調
べるために C デバッガで相当時間を費やした人がいました...

二つ目は、借用参照がスレッドに関係しているケースです。通常は、 Python
インタプリタにおける複数のスレッドは、グローバルインタプリタロックがオ
ブジェクト空間全体を保護しているため、互いに邪魔し合うことはありません
。とはいえ、ロックは "Py_BEGIN_ALLOW_THREADS" マクロで一時的に解除した
り、 "Py_END_ALLOW_THREADS" で再獲得したりできます。これらのマクロはブ
ロックの起こる I/O 呼び出しの周囲によく置かれ、 I/O が完了するまでの間
に他のスレッドがプロセッサを利用できるようにします。明らかに、以下の関
数は上の例と似た問題をはらんでいます:

   void
   bug(PyObject *list)
   {
       PyObject *item = PyList_GetItem(list, 0);
       Py_BEGIN_ALLOW_THREADS
       ...some blocking I/O call...
       Py_END_ALLOW_THREADS
       PyObject_Print(item, stdout, 0); /* BUG! */
   }


1.10.4. NULL ポインタ
---------------------

一般論として、オブジェクトへの参照を引数にとる関数はユーザが "NULL" ポ
インタを渡すとは予想しておらず、渡そうとするとコアダンプになる (か、あ
とでコアダンプを引き起こす) ことでしょう。一方、オブジェクトへの参照を
返すような関数は一般に、例外の発生を示す場合にのみ "NULL" を返します。
引数に対して "NULL" テストを行わない理由は、関数はしばしば受け取ったオ
ブジェクトを他の関数へと引き渡すからです --- 各々の関数が "NULL" テス
トを行えば、冗長なテストが大量に行われ、コードはより低速に動くことにな
ります。

従って、 "NULL" のテストはオブジェクトの "発生源"、すなわち値が "NULL"
になるかもしれないポインタを受け取ったときだけにしましょう。
"malloc()" や、例外を送出する可能性のある関数がその例です。

マクロ "Py_INCREF()" および "Py_DECREF()" は "NULL" ポインタのチェック
を行いません --- しかし、これらのマクロの変化形である "Py_XINCREF()"
および "Py_XDECREF()" はチェックを行います。

特定のオブジェクト型について調べるマクロ ("Pytype_Check()") は *NULL*
ポインタのチェックを行いません --- 繰り返しますが、様々な異なる型を想
定してオブジェクトの型を調べる際には、こうしたマクロを続けて呼び出す必
要があるので、個別に "NULL" ポインタのチェックをすると冗長なテストにな
ってしまうのです。型を調べるマクロには、 "NULL" チェックを行う変化形は
ありません。

Python から C 関数を呼び出す機構は、C 関数に渡される引数リスト (例でい
うところの "args") が決して "NULL" にならないよう保証しています --- 実
際には、常にタプル型になるよう保証しています。[4]

"NULL" ポインタを Python ユーザレベルに "逃がし" てしまうと、深刻なエ
ラーを引き起こします。


1.11. C++での拡張モジュール作成
===============================

C++でも拡張モジュールは作成できます。ただしいくつか制限があります。メ
インプログラム (Python インタプリタ) は C コンパイラでコンパイルされリ
ンクされているので、グローバル変数や静的オブジェクトをコンストラクタで
作成できません。メインプログラムが C++ コンパイラでリンクされているな
らこれは問題ではありません。 Python インタプリタから呼び出される関数 (
特にモジュール初期化関数) は、 "extern "C"" を使って宣言しなければなり
ません。また、Python ヘッダファイルを "extern "C" {...}" に入れる必要
はありません--- シンボル "__cplusplus" (最近の C++ コンパイラは全てこ
のシンボルを定義しています) が定義されているときに "extern "C" {...}"
が行われるように、ヘッダファイル内にすでに書かれているからです。


1.12. 拡張モジュールに C API を提供する
=======================================

多くの拡張モジュールは単に Python から使える新たな関数や型を提供するだ
けですが、時に拡張モジュール内のコードが他の拡張モジュールでも便利なこ
とがあります。例えば、あるモジュールでは順序概念のないリストのように動
作する "コレクション (collection)" クラスを実装しているかもしれません
。ちょうどリストを生成したり操作したりできる C API を備えた標準の
Python リスト型のように、この新たなコレクション型も他の拡張モジュール
から直接操作できるようにするには一連の C 関数を持っていなければなりま
せん。

一見するとこれは簡単なこと: 単に関数を (もちろん "static" などとは宣言
せずに) 書いて、適切なヘッダファイルを提供し、C API を書けばよいだけ、
に思えます。そして実際のところ、全ての拡張モジュールが Python インタプ
リタに常に静的にリンクされている場合にはうまく動作します。ところがモジ
ュールが共有ライブラリの場合には、一つのモジュールで定義されているシン
ボルが他のモジュールから不可視なことがあります。可視性の詳細はオペレー
ティングシステムによります; あるシステムは Python インタプリタと全ての
拡張モジュール用に単一のグローバルな名前空間を用意しています (例えば
Windows)。別のシステムはモジュールのリンク時に取り込まれるシンボルを明
示的に指定する必要があります (AIX がその一例です)、また別のシステム (
ほとんどの Unix) では、違った戦略を選択肢として提供しています。そして
、たとえシンボルがグローバル変数として可視であっても、呼び出したい関数
の入ったモジュールがまだロードされていないことだってあります!

従って、可搬性の点からシンボルの可視性には何ら仮定をしてはならないこと
になります。つまり拡張モジュール中の全てのシンボルは "static" と宣言せ
ねばなりません。例外はモジュールの初期化関数で、これは (モジュールのメ
ソッドテーブルと初期化関数 で述べたように) 他の拡張モジュールとの間で
名前が衝突するのを避けるためです。また、他の拡張モジュールからアクセス
を *受けるべきではない* シンボルは別のやり方で公開せねばなりません。

Python はある拡張モジュールの C レベルの情報 (ポインタ) を別のモジュー
ルに渡すための特殊な機構: Capsule (カプセル)を提供しています。 Capsule
はポインタ ("void *") を記憶する Python のデータ型です。 Capsule は C
API を介してのみ生成したりアクセスしたりできますが、他の Python オブジ
ェクトと同じように受け渡しできます。とりわけ、Capsule は拡張モジュール
の名前空間内にある名前に代入できます。他の拡張モジュールはこのモジュー
ルを import でき、次に名前を取得し、最後にCapsule へのポインタを取得し
ます。

拡張モジュールの C API を公開するために、様々な方法で Capsule が使われ
ます。各関数を1つのオブジェクトに入れたり、全ての C API のポインタ配列
を Capsule に入れることができます。そして、ポインタに対する保存や取得
といった様々な作業は、コードを提供しているモジュールとクライアントモジ
ュールとの間では異なる方法で分散できます。

どの方法を選ぶにしても、 Capsule の name を正しく設定することは重要で
す。 "PyCapsule_New()" は name 引数 ("const char *") を取ります。
"NULL" を name に渡すことも許可されていますが、 name を設定することを
強く推奨します。正しく名前を付けられた Capsule はある程度の実行時型安
全性を持ちます。名前を付けられていない Capsule を他の Capsule と区別す
る現実的な方法はありません。

特に、 C API を公開するための Capsule には次のルールに従った名前を付け
るべきです:

   modulename.attributename

"PyCapsule_Import()" という便利関数は、 Capsule の名前がこのルールに一
致しているときにのみ、簡単に Capsule 経由で公開されている C API をロー
ドすることができます。この挙動により、 C API のユーザーが、確実に正し
い C API を格納している Capsule をロードできたことを確かめることができ
ます。

以下の例では、名前を公開するモジュールの作者にほとんどの負荷が掛かりま
すが、よく使われるライブラリを作る際に適切なアプローチを実演します。こ
のアプローチでは、全ての C API ポインタ (例中では一つだけですが!) を、
Capsule の値となる "void" ポインタの配列に保存します。拡張モジュールに
対応するヘッダファイルは、モジュールの import と C API ポインタを取得
するよう手配するマクロを提供します; クライアントモジュールは、C API に
アクセスする前にこのマクロを呼ぶだけです。

名前を公開する側のモジュールは、 簡単な例 節の "spam" モジュールを修正
したものです。関数 "spam.system()" は C ライブラリ関数 "system()" を直
接呼び出さず、 "PySpam_System()" を呼び出します。この関数はもちろん、
実際には (全てのコマンドに "spam" を付けるといったような) より込み入っ
た処理を行います。この関数 "PySpam_System()" はまた、他の拡張モジュー
ルにも公開されます。

関数 "PySpam_System()" は、他の全ての関数と同様に "static" で宣言され
た通常の C 関数です:

   static int
   PySpam_System(const char *command)
   {
       return system(command);
   }

"spam_system()" には取るに足らない変更が施されています:

   static PyObject *
   spam_system(PyObject *self, PyObject *args)
   {
       const char *command;
       int sts;

       if (!PyArg_ParseTuple(args, "s", &command))
           return NULL;
       sts = PySpam_System(command);
       return PyLong_FromLong(sts);
   }

モジュールの先頭にある以下の行

   #include <Python.h>

の直後に、以下の二行を必ず追加してください:

   #define SPAM_MODULE
   #include "spammodule.h"

"#define" は、ファイル "spammodule.h" をインクルードしているのが名前を
公開する側のモジュールであって、クライアントモジュールではないことをヘ
ッダファイルに教えるために使われます。最後に、モジュールの初期化関数は
C API のポインタ配列を初期化するよう手配しなければなりません:

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       PyObject *m;
       static void *PySpam_API[PySpam_API_pointers];
       PyObject *c_api_object;

       m = PyModule_Create(&spammodule);
       if (m == NULL)
           return NULL;

       /* Initialize the C API pointer array */
       PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;

       /* Create a Capsule containing the API pointer array's address */
       c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

       if (PyModule_AddObject(m, "_C_API", c_api_object) < 0) {
           Py_XDECREF(c_api_object);
           Py_DECREF(m);
           return NULL;
       }

       return m;
   }

"PySpam_API" が "static" と宣言されていることに注意してください; そう
しなければ、 "PyInit_spam()" が終了したときにポインタアレイは消滅して
しまいます!

からくりの大部分はヘッダファイル "spammodule.h" 内にあり、以下のように
なっています:

   #ifndef Py_SPAMMODULE_H
   #define Py_SPAMMODULE_H
   #ifdef __cplusplus
   extern "C" {
   #endif

   /* Header file for spammodule */

   /* C API functions */
   #define PySpam_System_NUM 0
   #define PySpam_System_RETURN int
   #define PySpam_System_PROTO (const char *command)

   /* Total number of C API pointers */
   #define PySpam_API_pointers 1


   #ifdef SPAM_MODULE
   /* This section is used when compiling spammodule.c */

   static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;

   #else
   /* This section is used in modules that use spammodule's API */

   static void **PySpam_API;

   #define PySpam_System \
    (*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

   /* Return -1 on error, 0 on success.
    * PyCapsule_Import will set an exception if there's an error.
    */
   static int
   import_spam(void)
   {
       PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
       return (PySpam_API != NULL) ? 0 : -1;
   }

   #endif

   #ifdef __cplusplus
   }
   #endif

   #endif /* !defined(Py_SPAMMODULE_H) */

"PySpam_System()" へのアクセス手段を得るためにクライアントモジュール側
がしなければならないことは、初期化関数内での "import_spam()" 関数 (ま
たはマクロ) の呼び出しです:

   PyMODINIT_FUNC
   PyInit_client(void)
   {
       PyObject *m;

       m = PyModule_Create(&clientmodule);
       if (m == NULL)
           return NULL;
       if (import_spam() < 0)
           return NULL;
       /* additional initialization can happen here */
       return m;
   }

このアプローチの主要な欠点は、 "spammodule.h" がやや難解になるというこ
とです。とはいえ、各関数の基本的な構成は公開されるものと同じなので、書
き方を一度だけ学べばすみます。

最後に、Capsule は、自身に保存されているポインタをメモリ確保したり解放
したりする際に特に便利な、もう一つの機能を提供しているということに触れ
ておかねばなりません。詳細は Python/C API リファレンスマニュアルの カ
プセル, および Capsule の実装部分 (Python ソースコード配布物中のファイ
ル "Include/pycapsule.h" および "Objects/pycapsule.c" に述べられていま
す。

-[ 脚注 ]-

[1] この関数へのインタフェースはすでに標準モジュール "os" にあります
    --- この関数を選んだのは、単純で直接的な例を示したいからです。

[2] 参照を "借用する" というメタファは厳密には正しくありません: なぜな
    ら、参照の所有者は依然として参照のコピーを持っているからです。

[3] 参照カウントが 1 以上かどうか調べる方法は **うまくいきません** ---
    参照カウント自体も解放されたメモリ上にあるため、その領域が他のオブ
    ジェクトに使われている可能性があります!

[4] "旧式の" 呼び出し規約を使っている場合には、この保証は適用されませ
    ん --- 既存のコードにはいまだに旧式の呼び出し規約が多々あります。
