1. Extending Python with C or C++

It is quite easy to add new built-in modules to Python, if you know how to program in C. Such extension modules can do two things that can't be done directly in Python: they can implement new built-in object types, and they can call C library functions and system calls.

To support extensions, the Python API (Application Programmers Interface) defines a set of functions, macros and variables that provide access to most aspects of the Python run-time system. The Python API is incorporated in a C source file by including the header "Python.h".

The compilation of an extension module depends on its intended use as well as on your system setup; details are given in later chapters.

注釈

The C extension interface is specific to CPython, and extension modules do not work on other Python implementations. In many cases, it is possible to avoid writing C extensions and preserve portability to other implementations. For example, if your use case is calling C library functions or system calls, you should consider using the ctypes module or the cffi library rather than writing custom C code. These modules let you write Python code to interface with C code and are more portable between implementations of Python than writing and compiling a C extension module.

1.1. A Simple Example

Let's create an extension module called spam (the favorite food of Monty Python fans...) and let's say we want to create a Python interface to the C library function system() [1]. This function takes a null-terminated character string as argument and returns an integer. We want this function to be callable from Python as follows:

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

Begin by creating a file spammodule.c. (Historically, if a module is called spam, the C file containing its implementation is called spammodule.c; if the module name is very long, like spammify, the module name can be just spammify.c.)

The first two lines of our file can be:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

which pulls in the Python API (you can add a comment describing the purpose of the module and a copyright notice if you like).

注釈

Since Python may define some pre-processor definitions which affect the standard headers on some systems, you must include Python.h before any standard headers are included.

#define PY_SSIZE_T_CLEAN was used to indicate that Py_ssize_t should be used in some APIs instead of int. It is not necessary since Python 3.13, but we keep it here for backward compatibility. See 文字列とバッファ for a description of this macro.

All user-visible symbols defined by Python.h have a prefix of Py or PY, except those defined in standard header files.

Tip

For backward compatibility, Python.h includes several standard header files. C extensions should include the standard headers that they use, and should not rely on these implicit includes. If using the limited C API version 3.13 or newer, the implicit includes are:

  • <assert.h>

  • <intrin.h> (on Windows)

  • <inttypes.h>

  • <limits.h>

  • <math.h>

  • <stdarg.h>

  • <wchar.h>

  • <sys/types.h> (if present)

If Py_LIMITED_API is not defined, or is set to version 3.12 or older, the headers below are also included:

  • <ctype.h>

  • <unistd.h> (on POSIX)

If Py_LIMITED_API is not defined, or is set to version 3.10 or older, the headers below are also included:

  • <errno.h>

  • <stdio.h>

  • <stdlib.h>

  • <string.h>

The next thing we add to our module file is the C function that will be called when the Python expression spam.system(string) is evaluated (we'll see shortly how it ends up being called):

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);
}

There is a straightforward translation from the argument list in Python (for example, the single expression "ls -l") to the arguments passed to the C function. The C function always has two arguments, conventionally named self and args.

The self argument points to the module object for module-level functions; for a method it would point to the object instance.

The args argument will be a pointer to a Python tuple object containing the arguments. Each item of the tuple corresponds to an argument in the call's argument list. The arguments are Python objects --- in order to do anything with them in our C function we have to convert them to C values. The function PyArg_ParseTuple() in the Python API checks the argument types and converts them to C values. It uses a template string to determine the required types of the arguments as well as the types of the C variables into which to store the converted values. More about this later.

PyArg_ParseTuple() returns true (nonzero) if all arguments have the right type and its components have been stored in the variables whose addresses are passed. It returns false (zero) if an invalid argument list was passed. In the latter case it also raises an appropriate exception so the calling function can return NULL immediately (as we saw in the example).

1.2. Intermezzo: Errors and Exceptions

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);
}

1.3. Back to the Example

Going back to our example function, you should now be able to understand this statement:

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

It returns NULL (the error indicator for functions returning object pointers) if an error is detected in the argument list, relying on the exception set by PyArg_ParseTuple(). Otherwise the string value of the argument has been copied to the local variable command. This is a pointer assignment and you are not supposed to modify the string to which it points (so in Standard C, the variable command should properly be declared as const char *command).

The next statement is a call to the Unix function system(), passing it the string we just got from PyArg_ParseTuple():

sts = system(command);

Our spam.system() function must return the value of sts as a Python object. This is done using the function PyLong_FromLong().

return PyLong_FromLong(sts);

In this case, it will return an integer object. (Yes, even integers are objects on the heap in Python!)

If you have a C function that returns no useful argument (a function returning void), the corresponding Python function must return None. You need this idiom to do so (which is implemented by the Py_RETURN_NONE macro):

Py_INCREF(Py_None);
return Py_None;

Py_None is the C name for the special Python object None. It is a genuine Python object rather than a NULL pointer, which means "error" in most contexts, as we have seen.

1.4. The Module's Method Table and Initialization Function

I promised to show how spam_system() is called from Python programs. First, we need to list its name and address in a "method table":

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

Note the third entry (METH_VARARGS). This is a flag telling the interpreter the calling convention to be used for the C function. It should normally always be METH_VARARGS or METH_VARARGS | METH_KEYWORDS; a value of 0 means that an obsolete variant of PyArg_ParseTuple() is used.

When using only METH_VARARGS, the function should expect the Python-level parameters to be passed in as a tuple acceptable for parsing via PyArg_ParseTuple(); more information on this function is provided below.

The METH_KEYWORDS bit may be set in the third field if keyword arguments should be passed to the function. In this case, the C function should accept a third PyObject * parameter which will be a dictionary of keywords. Use PyArg_ParseTupleAndKeywords() to parse the arguments to such a function.

The method table must be referenced in the module definition structure:

static struct PyModuleDef spam_module = {
    ...
    .m_methods = spam_methods,
    ...
};

This structure, in turn, must be passed to the interpreter in the module's initialization function. The initialization function must be named PyInit_name(), where name is the name of the module, and should be the only non-static item defined in the module file:

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

Note that PyMODINIT_FUNC declares the function as PyObject * return type, declares any special linkage declarations required by the platform, and for C++ declares the function as extern "C".

PyInit_spam() is called when each interpreter imports its module spam for the first time. (See below for comments about embedding Python.) A pointer to the module definition must be returned via PyModuleDef_Init(), so that the import machinery can create the module and store it in sys.modules.

When embedding Python, the PyInit_spam() function is not called automatically unless there's an entry in the PyImport_Inittab table. To add the module to the initialization table, use PyImport_AppendInittab(), optionally followed by an import of the module:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

int
main(int argc, char *argv[])
{
    PyStatus status;
    PyConfig config;
    PyConfig_InitPythonConfig(&config);

    /* 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 */
    status = PyConfig_SetBytesString(&config, &config.program_name, argv[0]);
    if (PyStatus_Exception(status)) {
        goto exception;
    }

    /* Initialize the Python interpreter.  Required.
       If this step fails, it will be a fatal error. */
    status = Py_InitializeFromConfig(&config);
    if (PyStatus_Exception(status)) {
        goto exception;
    }
    PyConfig_Clear(&config);

    /* 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");
    }

    // ... use Python C API here ...

    return 0;

  exception:
     PyConfig_Clear(&config);
     Py_ExitStatusException(status);
}

注釈

If you declare a global variable or a local static one, the module may experience unintended side-effects on re-initialisation, for example when removing entries from sys.modules or importing compiled modules into multiple interpreters within a process (or following a fork() without an intervening exec()). If module state is not yet fully isolated, authors should consider marking the module as having no support for subinterpreters (via Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED).

A more substantial example module is included in the Python source distribution as Modules/xxlimited.c. This file may be used as a template or simply read as an example.

1.5. Compilation and Linkage

There are two more things to do before you can use your new extension: compiling and linking it with the Python system. If you use dynamic loading, the details may depend on the style of dynamic loading your system uses; see the chapters about building extension modules (chapter C および C++ 拡張のビルド) and additional information that pertains only to building on Windows (chapter Windows 上での C および C++ 拡張モジュールのビルド) for more information about this.

If you can't use dynamic loading, or if you want to make your module a permanent part of the Python interpreter, you will have to change the configuration setup and rebuild the interpreter. Luckily, this is very simple on Unix: just place your file (spammodule.c for example) in the Modules/ directory of an unpacked source distribution, add a line to the file Modules/Setup.local describing your file:

spam spammodule.o

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

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

spam spammodule.o -lX11

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

So far we have concentrated on making C functions callable from Python. The reverse is also useful: calling Python functions from C. This is especially the case for libraries that support so-called "callback" functions. If a C interface makes use of callbacks, the equivalent Python often needs to provide a callback mechanism to the Python programmer; the implementation will require calling the Python callback functions from a C callback. Other uses are also imaginable.

幸い、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;
}

This function must be registered with the interpreter using the METH_VARARGS flag; this is described in section The Module's Method Table and Initialization Function. The PyArg_ParseTuple() function and its arguments are documented in section 拡張モジュール関数でのパラメタ展開.

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);
if (arglist == NULL)
    return NULL;
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);

Note the placement of Py_DECREF(arglist) immediately after the call, before the error check!

位置引数とキーワード引数をサポートする PyObject_Call() を使うと、キーワード引数を指定して関数を呼び出すこともできます。 上の例と同じように、Py_BuildValue() を使って辞書を構築します。

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

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

The PyArg_ParseTuple() function is declared as follows:

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

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

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

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

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

#define PY_SSIZE_T_CLEAN
#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) */
}

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

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[] = {
    /* 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 keywdarg_module = {
    .m_base = PyModuleDef_HEAD_INIT,
    .m_name = "keywdarg",
    .m_size = 0,
    .m_methods = keywdarg_methods,
};

PyMODINIT_FUNC
PyInit_keywdarg(void)
{
    return PyModuleDef_Init(&keywdarg_module);
}

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() をちょうど 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() 関数) を提供するとともに、設定のためのインタフェースおよび検出機構を実行時に無効にする方法も提供しています。

1.10.1. 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() を呼び出す、という三つの方法があります。所有参照を処理し忘れると、メモリリークを引き起こします。

It is also possible to borrow [2] a reference to an object. The borrower of a reference should not call Py_DECREF(). The borrower must not hold on to the object longer than the owner from which it was borrowed. Using a borrowed reference after the owner has disposed of it risks using freed memory and should be avoided completely [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); /* 不具合あり! */
}

上の関数はまず、 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); /* 不具合あり! */
}

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 チェックを行う変化形はありません。

The C function calling mechanism guarantees that the argument list passed to C functions (args in the examples) is never NULL --- in fact it guarantees that it is always a tuple [4].

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

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

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

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

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

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

Portability therefore requires not to make any assumptions about symbol visibility. This means that all symbols in extension modules should be declared static, except for the module's initialization function, in order to avoid name clashes with other extension modules (as discussed in section The Module's Method Table and Initialization Function). And it means that symbols that should be accessible from other extension modules must be exported in a different way.

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 にアクセスする前にこのマクロを呼ぶだけです。

The exporting module is a modification of the spam module from section A Simple Example. The function spam.system() does not call the C library function system() directly, but a function PySpam_System(), which would of course do something more complicated in reality (such as adding "spam" to every command). This function PySpam_System() is also exported to other extension modules.

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) を参照してください。

脚注