読者です 読者をやめる 読者になる 読者になる

たまに書きます。

気になって調べたことを書いていきます。まずはAboutページをご覧ください。

CythonでCのモジュールにnumpyオブジェクトを渡す

CythonはPythonのコードをCのコードに変換して(このフェーズをCythoningというみたい)、Pythonから呼び出せるライブラリを構築するツール。
Cythonが素晴らしいのは、Pythonコードを高速に実行できるようにするだけではなく、C言語で書かれたコードやライブラリを直に呼ぶことができる点。
詳しくは、
http://docscythonja.zouri.jp/index.html
http://docs.cython.org/
とかを参照。

ただ、numpyのオブジェクトをcythonを用いてCのコードに渡す方法、というのがそれをやったという人の情報はあるんだけど、実際に「ただ渡す」にはどういうコードにすればいいのか、というのがなかなか見つからなくて自分も結構苦労したのでここにメモ。
本家ドキュメントを通して読んだわけではないのでなんとも言えないが、近いものとしてはこんな感じか?http://docs.cython.org/src/userguide/numpy_tutorial.html#numpy-tutorial

で、いいからとりあえずnumpyを渡したい!という時のサンプルとしてはこんな感じ。

これを一式落として、compile.shを実行する。ちなみにsetup.pyのところの日本語のコメントは消さないとビルド通りません。Macの場合はこのコメントを消すだけでOKだけど、LinuxとかWindows環境の場合はこの下のnumpy_includeを適切なパラメータに買えないとダメです。
ビルドが通ったら、sample.pyが実行できて、

$python sample.py
0
0
0
0
0
==================================
1000
1000
1200
1500

っていう結果になるはず。

結局、重要な点は、
・*.pyxのファイルの中で、numpyをimportおよびcimportする。
・setup.pyの中で、Extensionにnumpy関係のヘッダのおいてある場所をインクルードパスとして渡す。ちなみに、僕のMacで渡してるこのディレクトリの中には

/System/Library/Frameworks/Python.framework/Versions/Current/Extras/lib/python/numpy/core/include/numpy% ls   
__multiarray_api.h           ndarraytypes.h               npy_os.h
__ufunc_api.h                noprefix.h                   numpyconfig.h
_neighborhood_iterator_imp.h npy_3kcompat.h               old_defines.h
_numpyconfig.h               npy_common.h                 oldnumeric.h
arrayobject.h                npy_cpu.h                    ufunc_api.txt
arrayscalars.h               npy_endian.h                 ufuncobject.h
multiarray_api.txt           npy_interrupt.h              utils.h
ndarrayobject.h              npy_math.h

てな感じであって、この中で特に重要なのがndarrayobject.hとかufuncobject.h。これらがCythoningされたコードから直にincludeされて宣言が取り込まれるみたいです。
・C側は配列の大きさまではわからない(これはCをやってれば当たり前だけど)。そこでサイズを渡すとかしてサイズが分かるようにすること。

これらを守ってやれば、setup.pyのExtensionとかでlanguage='c++'とか指定してあげればC++コードをCythonから呼ぶときも同じようにして呼び出せる。