C API の使用: その他の話題
**************************

チュートリアル では C API 拡張モジュールの作り方を説明しましたが、まだ
説明していない領域が数多くあります。 この文書では、より複雑な拡張を書
くために必要な概念をいくつか取り上げます。


エラーと例外
============

An important convention throughout the Python interpreter is the
following: when a function fails, it should set an exception condition
and return an error value (usually "-1" or a "NULL" pointer).
Exception information is stored in three members of the interpreter's
thread state.  These are "NULL" if there is no exception.  Otherwise
they are the C equivalents of the members of the Python tuple returned
by "sys.exc_info()".  These are the exception type, exception
instance, and a traceback object.  It is important to know about them
to understand how errors are passed around.

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_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_OSError" が適切です)。 引数リストに
問題がある場合、"PyArg_ParseTuple()" 関数は通常 "PyExc_TypeError" を送
出します。 引数の値が特定の範囲内でなければならない場合や、その他の条
件を満たす必要がある場合は、"PyExc_ValueError" が適切です。

モジュール独自の新しい例外を定義することもできます。 最も簡単な方法は
、ファイルの先頭で静的なグローバルオブジェクト変数を宣言することです。

   static PyObject *SpamError = NULL;

そして、モジュールの "Py_mod_exec" 関数 ("spam_module_exec()") で
"PyErr_NewException()" を呼び出して初期化します。

   SpamError = PyErr_NewException("spam.error", NULL, NULL);

"SpamError" はグローバル変数なので、モジュールが再初期化されて
"Py_mod_exec" 関数が呼び出されるたびに上書きされます。

ひとまず、この問題は回避しましょう。 "ImportError" を送出して、初期化
が繰り返されるのを防ぎます。

   static PyObject *SpamError = NULL;

   static int
   spam_module_exec(PyObject *m)
   {
       if (SpamError != NULL) {
           PyErr_SetString(PyExc_ImportError,
                           "cannot initialize spam module more than once");
           return -1;
       }
       SpamError = PyErr_NewException("spam.error", NULL, NULL);
       if (PyModule_AddObjectRef(m, "SpamError", SpamError) < 0) {
           return -1;
       }

       return 0;
   }

   static PyModuleDef_Slot spam_module_slots[] = {
       {Py_mod_exec, spam_module_exec},
       {0, NULL}
   };

   static struct PyModuleDef spam_module = {
       .m_base = PyModuleDef_HEAD_INIT,
       .m_name = "spam",
       .m_size = 0,  // 非負の値
       .m_slots = spam_module_slots,
   };

   PyMODINIT_FUNC
   PyInit_spam(void)
   {
       return PyModuleDef_Init(&spam_module);
   }

例外オブジェクトの Python での名前は "spam.error" であることに注意して
ください。 "PyErr_NewException()" 関数は、"NULL" の代わりに別のクラス
を渡さなければ、組み込み例外 で説明する "Exception" を基底クラスとする
クラスを作成できます。

"SpamError" 変数が新しく作成した例外クラスへの参照を保持している点にも
注意してください。 これは意図的なものです。 外部のコードがモジュールか
ら例外を削除する可能性があるため、クラスへの参照を所有しておく必要があ
ります。 そうすることで、クラスが破棄されて "SpamError" がダングリング
ポインターになるのを防ぎます。 ダングリングポインターになると、その例
外を送出する C コードがコアダンプなどの意図しない副作用を引き起こすお
それがあります。

現時点では、この参照を解放する "Py_DECREF()" 呼び出しがありません。
Python インタープリタが終了しても、グローバル変数 "SpamError" はガベー
ジコレクションの対象にならず、「リーク」します。 ただし、これが起こる
のはプロセスあたり最大 1 回となるようにしてあります。

We discuss the use of "PyMODINIT_FUNC" as a function return type later
in this sample.

次のように "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);
   }


拡張モジュールの組み込み
========================

モジュールを Python インタープリタの恒久的な構成要素にするには、設定を
変更してインタープリタを再ビルドする必要があります。 Unix では、ソース
配布物を展開した "Modules/" ディレクトリにファイル (例えば
"spammodule.c") を置き、"Modules/Setup.local" にそのファイルを記述する
行を追加します。

   spam spammodule.o

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

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

   spam spammodule.o -lX11


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

チュートリアルでは、Python から C 関数を呼び出せるようにする方法に注目
しました。 その逆、つまり C から Python 関数を呼び出すことも有用です。
特に、いわゆる「コールバック」関数をサポートするライブラリでは役立ちま
す。 C のインターフェースがコールバックを利用する場合、それに対応する
Python のインターフェースでも、Python プログラマーにコールバックの仕組
みを提供する必要があることがよくあります。 その実装には、C のコールバ
ックから Python のコールバック関数を呼び出す処理が必要です。 ほかの用
途も考えられます。

幸い、Python インタープリタは簡単に再帰的に呼び出せますし、Python 関数
を呼び出すための標準インターフェースがあります。 (特定の文字列を入力と
して Python のパーサーを呼び出す方法については、超高水準レイヤ を参照
してください。)

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);         /* 新しいコールバックへの参照を追加する */
           Py_XDECREF(my_callback);  /* 以前のコールバックを解放する */
           my_callback = temp;       /* 新しいコールバックを保存する */
           /* "None" を返すための定型処理 */
           Py_INCREF(Py_None);
           result = Py_None;
       }
       return result;
   }

この関数は、"PyMethodDef.ml_flags" に "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;
   ...
   /* コールバックを呼び出す */
   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()" を呼び出す必要があります。 戻り値を使わない場合も (特に
そのような場合こそ) 必要です。

ただし、その前に戻り値が "NULL" でないことを確認する必要があります。
"NULL" なら、Python 関数は例外を送出して終了しています。
"PyObject_CallObject()" を呼び出した C コード自体が Python から呼び出
されている場合は、Python の呼び出し元にエラーを示す値を返す必要があり
ます。 これにより、インタープリタがスタックトレースを表示したり、呼び
出し元の Python コードが例外を処理したりできます。 そうすることが不可
能、または望ましくない場合は、"PyErr_Clear()" を呼び出して例外を消去す
る必要があります。 例えば、次のようにします。

   if (result == NULL)
       return NULL; /* 呼び出し元にエラーを返す */
   ...use result...
   Py_DECREF(result);

Python のコールバック関数にどのようなインターフェースを用意するかによ
っては、"PyObject_CallObject()" に引数リストを渡す必要もあります。 コ
ールバック関数を指定するインターフェースを通じて、Python プログラムが
引数リストも渡す場合があります。 その場合は、関数オブジェクトと同じ方
法で保存して使えます。 一方、引数リストとして渡す新しいタプルを構築し
なければならない場合もあります。 最も簡単な方法は "Py_BuildValue()" を
呼び出すことです。 例えば、整数のイベントコードを渡すには、次のように
書けます。

   PyObject *arglist;
   ...
   arglist = Py_BuildValue("(l)", eventcode);
   result = PyObject_CallObject(my_callback, arglist);
   Py_DECREF(arglist);
   if (result == NULL)
       return NULL; /* 呼び出し元にエラーを返す */
   /* 必要ならここで結果を使う */
   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);


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

チュートリアル では「"METH_O"」関数を使いましたが、これは Python の引
数を 1 個だけ受け取れます。 より多くの引数が必要なら、代わりに
"METH_VARARGS" を使えます。 このフラグを指定すると、C 関数は単一のオブ
ジェクトではなく、引数の "tuple" を受け取ります。

タプルの要素を取り出すために、CPython は次のように宣言された
"PyArg_ParseTuple()" 関数を提供しています。

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

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

例えば、Python の "str" オブジェクトを 1 個受け取って C のバッファーに
変換するには、書式文字列に ""s"" を指定します。

   const char *command;
   if (!PyArg_ParseTuple(args, "s", &command)) {
       return NULL;
   }

If an error is detected in the argument list, "PyArg_ParseTuple()"
returns "NULL" (the error indicator for functions returning object
pointers); your function may return "NULL", relying on the exception
set by "PyArg_ParseTuple()".

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

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

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

   #include <Python.h>

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

   ok = PyArg_ParseTuple(args, ""); /* 引数なし */
       /* Python での呼び出し: f() */

   ok = PyArg_ParseTuple(args, "s", &s); /* 文字列 */
       /* Python での呼び出し例: f('whoops!') */

   ok = PyArg_ParseTuple(args, "lls", &k, &l, &s); /* long 型の値 2 個と文字列 */
       /* Python での呼び出し例: f(1, 2, 'three') */

   ok = PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);
       /* int 型の値のペアと文字列。
          文字列のサイズも取得する */
       /* Python での呼び出し例: f((1, 2), 'three') */

   {
       const char *file;
       const char *mode = "r";
       int bufsize = 0;
       ok = PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);
       /* 文字列と、省略可能な別の文字列および整数 */
       /* Python での呼び出し例:
          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);
       /* 長方形と点 */
       /* Python での呼び出し例:
          f(((0, 0), (400, 300)), (10, 10)) */
   }

   {
       Py_complex c;
       ok = PyArg_ParseTuple(args, "D:myfunction", &c);
       /* 複素数。
          エラー用の関数名も指定する */
       /* Python での呼び出し例: myfunction(1+2j) */
   }


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

関数が *キーワード引数* も受け取れるようにするには、"METH_VARARGS" と
組み合わせて "METH_KEYWORDS" フラグを使います。 ("METH_KEYWORDS" はほ
かのフラグとも組み合わせられます。 使用できる組み合わせについては、そ
のドキュメントを参照してください。)

この場合、C 関数はキーワード引数の辞書を受け取るための 3 番目の引数を
"PyObject *" 型で受け取る必要があります。 このような関数の引数を解析す
るには "PyArg_ParseTupleAndKeywords()" を使います。

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

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

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

注釈:

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

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

   #define PY_SSIZE_T_CLEAN
   #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[] = {
       /* PyCFunction は PyObject* 引数を 2 個だけ受け取るのに対し、
        * keywdarg_parrot() は 3 個受け取るため、関数のキャストが必要。
        */
       {"parrot", (PyCFunction)(void(*)(void))keywdarg_parrot, METH_VARARGS | METH_KEYWORDS,
        "楽しい寸劇を標準出力に表示します。"},
       {NULL, NULL, 0, NULL}   /* 終端 */
   };


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

"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))


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

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

"malloc()" で確保したメモリブロックは、最終的に "free()" をちょうど 1
回呼び出して、利用可能なメモリのプールに戻す必要があります。 "free()"
を適切なタイミングで呼び出すことが重要です。 "free()" を呼び出さないま
まブロックのアドレスを失うと、そのメモリはプログラムが終了するまで再利
用できません。 これをメモリリーク (*memory leak*) と呼びます。 一方、
"free()" を呼び出した後もそのブロックを使い続けると、別の "malloc()"
呼び出しによるブロックの再利用と競合します。 これを解放済みメモリの使
用 (*using freed memory*) と呼びます。 初期化していないデータへの参照
と同様に、コアダンプ、誤った結果、不可解なクラッシュといった悪影響があ
ります。

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

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

別の方法として、自動ガベージコレクション (*automatic garbage
collection*) があります。 (参照カウント法もガベージコレクションの方法
と呼ばれることがあるため、両者を区別するために「自動」と付けています。
) 自動ガベージコレクションの大きな利点は、利用者が "free()" を明示的に
呼び出す必要がないことです。 (速度やメモリ使用量の改善も利点として挙げ
られますが、これは確実な事実ではありません。) 欠点は、C には真に移植性
のある自動ガベージコレクターがないことです。 一方、参照カウント法は移
植可能な形で実装できます ("malloc()" と "free()" が利用できる限りです
が、これは C 規格で保証されています)。 いつかは C でも十分に移植性のあ
る自動ガベージコレクターが使えるようになるかもしれません。 それまでは
参照カウントを使っていく必要があります。

Python は従来の参照カウント法に加えて、循環参照を検出する仕組みも備え
ています。 これにより、アプリケーションは直接または間接的な循環参照が
できることを心配せずに済みます。 循環参照は、参照カウント法だけで実装
したガベージコレクションの弱点です。 循環参照は、直接または間接的に自
分自身への参照を持つオブジェクトからなり、循環内の各オブジェクトの参照
カウントはゼロではありません。 通常の参照カウント法の実装では、循環そ
のものへの参照がほかになくなっても、循環内のオブジェクトや、そこから参
照されるオブジェクトのメモリを回収できません。

循環参照検出機構はそのようなガベージサイクル (前述したような循環参照オ
ブジェクト) を検出して回収することができます。 "gc" モジュールそのよう
な検出機構の実行 ("collect()" 関数) を提供するとともに、設定のためのイ
ンタフェースおよび検出機構を実行時に無効にする方法も提供しています。


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*) [1] することもできます。 参照を
借用した側は "Py_DECREF()" を呼び出してはいけません。 また、借用元の所
有者よりも長くオブジェクトを保持してはいけません。 所有者が参照を手放
した後に借用参照を使うと、解放済みメモリを使うおそれがあるため、絶対に
避けてください [2]。

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

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


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

オブジェクトへの参照を関数に渡す場合も、関数から返す場合も、その参照の
所有権を一緒に移すかどうかは、関数のインターフェース仕様の一部です。

オブジェクトへの参照を返すほとんどの関数は、参照とともに所有権も渡しま
す。特に、 "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 関数が返す参照は所有参照でなければなりません
--- 所有権は関数から呼び出し側へと委譲されます。


薄氷
----

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

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

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

       PyList_SetItem(list, 1, PyLong_FromLong(0L));
       PyObject_Print(item, stdout, 0); /* 不具合あり! */
   }

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

"PyList_SetItem()" の中での処理を追ってみましょう。 リストはすべての要
素への参照を所有しているため、インデックス 1 の要素を置き換える際には
、元の要素への参照を手放す必要があります。 元の要素がユーザー定義クラ
スのインスタンスで、そのクラスに "__del__()" メソッドが定義されている
とします。 このインスタンスの参照カウントが 1 なら、参照を手放すことで
"__del__()" メソッドが呼び出されます。 内部では、"PyList_SetItem()" が
置き換えた要素に対して "Py_DECREF()" を呼び出し、その要素に対応する
"tp_dealloc" 関数が呼び出されます。 解放処理中に "tp_dealloc" は
"tp_finalize" を呼び出します。 クラスのインスタンスでは、これは
"__del__()" メソッドに対応します (**PEP 442** を参照)。 この一連の処理
はすべて、"PyList_SetItem()" の呼び出し内で同期的に行われます。

"__del__()" メソッドは Python で書かれているため、任意の Python コード
を実行できます。 では、"bug()" 内の "item" への参照を無効にすることも
できるでしょうか。 もちろんできます。 "bug()" に渡されたリストに
"__del__()" メソッドからアクセスできれば、"del 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 のデバ
ッガーでかなりの時間を費やした人がいました。

借用参照で問題になる 2 つ目のケースは、スレッドが関わるものです。 通常
、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); /* 不具合あり! */
   }


NULL ポインタ
-------------

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

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

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

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

C 関数の呼び出しの仕組みにより、C 関数に渡される引数リスト (例の
"args") は決して "NULL" にならず、常にタプルであることが保証されます
[3]。

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


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

C++ でも拡張モジュールを作成できますが、いくつか制限があります。 メイ
ンプログラム (Python インタープリタ) を C コンパイラでコンパイルしてリ
ンクする場合、コンストラクターを持つグローバルオブジェクトや静的オブジ
ェクトは使えません。 メインプログラムを C++ コンパイラでリンクする場合
は問題ありません。 Python インタープリタから呼び出される関数 (特にモジ
ュール初期化関数) は、"extern "C"" を使って宣言する必要があります。
Python のヘッダーファイルを "extern "C" {...}" で囲む必要はありません
。 シンボル "__cplusplus" が定義されていれば、ヘッダーファイル自体がこ
の形式を使います (最近の C++ コンパイラはすべてこのシンボルを定義しま
す)。


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

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

一見すると簡単そうです。 関数を書き (もちろん "static" は付けずに)、適
切なヘッダーファイルを用意し、C API の使い方を文書化すればよさそうです
。 実際、すべての拡張モジュールを常に Python インタープリタに静的にリ
ンクするのであれば、この方法で動作します。 しかし、モジュールを共有ラ
イブラリとして使う場合、あるモジュールで定義したシンボルが別のモジュー
ルから見えるとは限りません。 可視性の詳細はオペレーティングシステムに
よって異なります。 Python インタープリタとすべての拡張モジュールで単一
のグローバルな名前空間を使うシステムもあれば (例えば Windows)、 モジュ
ールのリンク時にインポートするシンボルを明示的に列挙する必要があるシス
テム (例えば AIX) や、 複数の方式から選べるシステム (ほとんどの Unix)
もあります。 そして、シンボルがどこからでも見える場合でも、呼び出した
い関数のあるモジュールがまだロードされていないかもしれません。

そのため、移植性を確保するにはシンボルの可視性について何も仮定しないこ
とが必要です。 つまり、ほかの拡張モジュールとの名前の衝突を避けるため
、モジュール初期化関数以外のすべてのシンボルを "static" として宣言する
べきです。 また、ほかの拡張モジュールからアクセス *できるようにしたい*
シンボルは、別の方法で公開する必要があります。

Python は、拡張モジュール間で C レベルの情報 (ポインター) を渡すための
特別な仕組みとして Capsule を提供しています。 Capsule はポインター
(void*) を格納する Python のデータ型です。 作成や内容へのアクセスは C
API 経由でしかできませんが、ほかの Python オブジェクトと同様に受け渡せ
ます。 特に、拡張モジュールの名前空間にある名前に代入できます。 ほかの
拡張モジュールはそのモジュールをインポートし、その名前に対応する値を取
得して、Capsule の中からポインターを取り出せます。

Capsule を使って拡張モジュールの C API を公開する方法はいくつもありま
す。 関数ごとに専用の Capsule を用意してもよいですし、すべての 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 にア
クセスする前にこのマクロを呼ぶだけです。

API を公開するモジュールは、チュートリアル の "spam" モジュールを変更
したものです。 "spam.system()" は C ライブラリの "system()" を直接呼ば
ず、"PySpam_System()" を呼び出します。 実際には、この関数はもっと複雑
な処理 (例えばすべてのコマンドに "spam" を追加するなど) を行うでしょう
。 この "PySpam_System()" 関数を、ほかの拡張モジュールにも公開します。

"PySpam_System()" は普通の C 関数で、ほかと同じく "static" として宣言
します。

   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" は、ヘッダーファイルがクライアントモジュールではなく
API を公開するモジュールからインクルードされていることを伝えます。 最
後に、モジュールの "mod_exec" 関数で C API ポインター配列を初期化する
必要があります。

   static int
   spam_module_exec(PyObject *m)
   {
       static void *PySpam_API[PySpam_API_pointers];
       PyObject *c_api_object;

       /* C API ポインターの配列を初期化する */
       PySpam_API[PySpam_System_NUM] = (void *)PySpam_System;

       /* API ポインター配列のアドレスを格納した Capsule を作成する */
       c_api_object = PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

       if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
           return -1;
       }

       return 0;
   }

Note that "PySpam_API" is declared "static"; otherwise the pointer
array would disappear when "PyInit_spam()" terminates!

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

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

   /* spammodule のヘッダーファイル */

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

   /* C API ポインターの総数 */
   #define PySpam_API_pointers 1


   #ifdef SPAM_MODULE
   /* この部分は spammodule.c のコンパイル時に使う */

   static PySpam_System_RETURN PySpam_System PySpam_System_PROTO;

   #else
   /* この部分は spammodule の API を使うモジュールで使う */

   static void **PySpam_API;

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

   /* エラー時は -1、成功時は 0 を返す。
    * エラーがあれば PyCapsule_Import が例外を設定する。
    */
   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) */

All that a client module must do in order to have access to the
function "PySpam_System()" is to call the function (or rather macro)
"import_spam()" in its "mod_exec" function:

   static int
   client_module_exec(PyObject *m)
   {
       if (import_spam() < 0) {
           return -1;
       }
       /* 必要ならここで追加の初期化を行う */
       return 0;
   }

この方法の主な欠点は、"spammodule.h" がやや複雑になることです。 ただし
、公開するどの関数でも基本構造は同じなので、一度覚えれば済みます。

最後に、Capsule には追加の機能もあり、特に格納するポインターに関わるメ
モリの確保や解放に役立ちます。 詳細は、Python/C API リファレンスマニュ
アルの カプセル と、Capsule の実装 (Python のソース配布物にある
"Include/pycapsule.h" と "Objects/capsule.c") を参照してください。

-[ 脚注 ]-

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

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

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