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

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

幸運なことに、Python インタプリタは簡単に再帰呼び出しでき、 Python 関数を呼び出すための標準インタフェースもあります。 (Python パーザを特定の入力文字を使って呼び出す方法について 詳説するつもりはありません -- この方法に興味があるなら、 Python ソースコードの Python/pythonmain.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);         /* 新たなコールバックへの参照を追加 */
        Py_XDECREF(my_callback);  /* 以前のコールバックを捨てる */
        my_callback = temp;       /* 新たなコールバックを記憶 */
        /* "None" を返す際の定型句 */
        Py_INCREF(Py_None);
        result = Py_None;
    }
    return result;
}

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

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

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

    int arg;
    PyObject *arglist;
    PyObject *result;
    ...
    arg = 123;
    ...
    /* ここでコールバックを呼ぶ */
    arglist = Py_BuildValue("(i)", arg);
    result = PyEval_CallObject(my_callback, arglist);
    Py_DECREF(arglist);

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

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

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

    if (result == NULL)
        return NULL; /* エラーを返す */
    ...use result...
    Py_DECREF(result);

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

    PyObject *arglist;
    ...
    arglist = Py_BuildValue("(l)", eventcode);
    result = PyEval_CallObject(my_callback, arglist);
    Py_DECREF(arglist);
    if (result == NULL)
        return NULL; /* エラーを返す */
    /* 場合によってはここで結果を使うかもね */
    Py_DECREF(result);

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

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。