Python拡張モジュールの作成(MinGW)
以下のような動作をするPython拡張モジュールの作成方法です。拡張モジュール名はspamとし、system()というメソッドを有するものとします。環境はPython 2.7、コンパイラはMinGW上のgcc 4.5.2です。サンプルコードの出典はhttp://docs.python.org/extending/です。
>>> import spam >>> status = spam.system("dir /w")
拡張モジュールのソースコードを下記に示します。受け取った文字列を引数としてsystem()をコールするだけの単純な処理です。
- spammodule.c
#include <Python.h> 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); } static PyMethodDef SpamMethods[] = { {"system", spam_system, METH_VARARGS, "Execute a shell command."}, {NULL, NULL, 0, NULL} /* Sentinel */ }; PyMODINIT_FUNC initspam(void) { (void) Py_InitModule("spam", SpamMethods); }
pydに必要となるdefファイルを作成します。詳細はわかりませんが、「init+モジュール名」なる関数(このサンプルの場合はinitspam)の外部公開は必須のようです。
- spam.def
LIBRARY spam.pyd EXPORTS initspam
$ gcc -c spammodule.c -I/c/python27/include $ dllwrap -def spam.def -driver-name gcc --dllname spam.pyd -o spam.pyd \ --target=i386-mingw32 --mno-cygwin spammodule.o \ -L/c/Python27/Libs -lpython27 -static-libgcc
dllwrapのオプションに-static-libgccをつけると生成されたspam.pydがlibgcc_s_dw2-1.dllに外部依存しなくなるので便利です。(外部依存させる場合、Pythonのsys.pathにlibgcc_s_dw2-1.dllを置く必要があります。)また、libstdc++-6.dllに外部依存させないようにするには-static-libstdc++を指定するとよいようです。pydがどのDLLに依存しているかを見るにはDependency Walkerが役立ちました。