#
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 にもできます。)

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

    #include <Python.h>

これで、Python API を取り込みます (必要なら、モジュールの用途に 関する説明や、著作権表示を追加します)。 Python は、システムによっては標準ヘッダの定義に影響するような プリプロセッサ定義を行っているので、 Python.h は いずれの標準ヘッダよりも前にインクルードせねばなりません。

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 Py_BuildValue("i", sts);
    }

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

self 引数は C 関数が Python の関数ではなく組み込みメソッド を実装している場合にのみ使われます。この例ではメソッドではなく 関数を定義しているので、 self は常に `NULL` ポインタになります。 (これは、インタプリタが二つの異なる形式の C 関数を理解しなくてもよく するためです。)

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

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

#### Footnotes

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