「Cython Cとの融合によるPythonの高速化」オライリーから
C言語で書かれた関数をPythonでimportして実行できることをUbuntu上でたどってみた。
まずは、この本のサンプルがgithub上にあるのでzipファイルでまとめてダウンロードする。
https://github.com/cythonbook/examples
展開してできたディレクトリに移動する。
examples-master/07-wrapping-c/01-wrapping-c-functions-mt-random
ここにはMakefileがあるのでmakeしてみる。
そうすると必要なファイルができたようで
同書p128にある例がIPythonから動作する。
In [1]: import mt_random
In [2]: mt_random.init_state(42)
In [3]: mt_random.rand()
Out[3]: 0.37454011439684315
確かに、本に書かれているようにCythonでC関数をラップできている。
まず、Cのソースファイルとヘッダファイルとがあること。
Cythonにおける外部Cコードの宣言(拡張子 .pxd)
cdef extern from "mt19937ar.h":
void init_genrand(unsigned long s)
double genrand_real1()
C関数のラップ(拡張子 .pyx)
# distutils: sources=["mt19937ar.c"]
cimport mt
def init_state(unsigned long s):
mt.init_genrand(s)
def rand():
return mt.genrand_real1()
コンパイルの方法を指示するsetup.pyファイル
from distutils.core import setup, Extension
from Cython.Build import cythonize
ext = Extension("mt_random",
sources=["mt_random.pyx", "mt19937ar.c"])
setup(name="mersenne_random",
ext_modules = cythonize([ext]))
そしてsetup.pyを実行するMakefileが既にzipファイルの中に含まれていた。
これをmakeすれば先ほどの実行結果になりました。
pxdファイル, pyxファイル, setup.pyを書くことでwrapできることがわかりました。
このようにして実装したmt_randomモジュールについて
help(mt_random)
とすると
以下のようにhelpが表示されるのも便利です。
Help on module mt_random:
NAME
mt_random
FILE
/(略)/examples-master/07-wrapping-c/01-wrapping-c-functions-mt-random/mt_random.so
FUNCTIONS
init_state(...)
rand(...)
DATA
test = {}
この例題以上のことを理解するには、同書の7章を読むことのようです。
全てをC言語で書かなくても、ボトルネック部分だけをC言語で書いて
Cythonを使ってラッパーを書けば十分になるというのはうれしい限りです。