モジュールの作成

2010年2月21日

ファイル

03-module.tar.gz

内容

C で Python のモジュールを作ってみましょう。まず、モジュールの名前を決めましょう。まんま "module" とします。これがもつメソッドを決めましょう。ここでは、"Hello" とだけ出力する sayHello() メソッドをもつものとしましょう。つまり、次のようになるようにしたいわけです。

>>> import module
>>> module.sayHello()
Hello

まず、sayHello() の実装は次のようになります。

static PyObject* module_sayHello(PyObject *self, PyObject *args)
{
	printf("Hello\n");

	return Py_BuildValue("");
}

PyObject は、Python で使われる一般的なオブジェクトを表わす型です。メソッドは引数として self, args を受け取ります。メソッド名はなんでもよい (はず) ですが、わかりやすく "モジュール名_メソッド名" としておきます。Py_BuildValue() は PyObject を作るための関数です。printf() のように文字列でフォーマットを指定してオブジェクトを作ることができますが、ここでは特に返すものはないので、空のオブジェクトを返しています。

PyObject を作るための関数はいろいろあり、たとえば、C の文字列から Python の文字列オブジェクトを作る PyString_FromString() などがあります。詳しくは "Python/C API Reference Manual" を参照してください。

さて、メソッドの情報を格納した配列を用意します。

static PyMethodDef methods[] = {
	{"sayHello", module_sayHello, METH_VARARGS, "Say hello."},
	{NULL, NULL, 0, NULL}
};

PyMethodDef 構造体の最初のフィールドにはメソッド名をセットします。2 番目はメソッドを実装した関数を指定します。3 番目は関数が受け取る引数の種類で、ここでは self, args を受け取るように指定しています。4 番目はメソッドの説明で、Python の help() で表示される文字列です。配列の最後にあるのは配列の終わりを表わすものです。

モジュールには初期化が必要です。

PyMODINIT_FUNC
initmodule(void)
{
	PyObject *m;

	m = Py_InitModule("module", methods);
	if(m == NULL) return;
}

これはモジュールのインポート時に呼ばれます。初期化の関数の頭には PyMODINIT_FUNC を指定し、関数の名前は "initモジュール名" とする必要があります。Py_InitModule() にモジュール名とモジュールのメソッドの情報を渡してモジュールを初期化しています。

モジュールは、Windows の場合は DLL にする必要があります。ただし名前は "ほにゃらら.dll" ではなく、Python モジュール用に "ほにゃらら.pyd" とします。Makefile の記述は次のようになります。

LDFLAGS = -shared
INCLUDES = -I/c/Python26/include
LIBS = -L/c/Python26/libs -lpython26

TARGET = module.pyd

作るファイル名を "module.pyd" にし、リンカのオプションに "-shared" を指定しています。

実行してみましょう。

$ python
Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import module
>>> dir(module)
['__doc__', '__file__', '__name__', '__package__', 'sayHello']

ちゃんとインポートできましたし、sayHello() もあります。

>>> help(module.sayHello)
Help on built-in function sayHello in module module:

sayHello(...)
    Say hello.

sayHello() の説明もばっちり表示されました。

>>> module.sayHello()
Hello

はじめの期待どおりに動きました。

C で Python を使う 目次へ