必要な環境
- Python
- pip (Python 3.xの場合は標準でついてくる)
- Pythonに合ったコンパイラ環境
- Macの場合はXcodeのcommand-line toolsが必要…なはず。
- Windowsの場合、Visual Studioに加えて"Python compiler"だとかいうツールをインストールしなければならなかった気がする。
- その他Unixの場合は、すでにgccやらが入っているはず。
(2020.04.05追記)
Windowsの場合、コンパイルできるようになるまでの道のりがけっこうややこしい。いちおうCython公式ページにいろいろなヒントが書かれているけれど…読むのはだるい:
- Pythonのコンパイル環境を手に入れるための記事:最近のバージョンの場合、Windows SDK C/C++ Compilerなるものが必要らしい。基本的にはPythonがビルドされたバージョンのWindows SDKのコンパイラが必要(詳しくはこのPython wikiページを参照)
- Anaconda etc.でインストールするためのヒント:ここにはそこまで目新しい情報はないけれど、念のため
さらにCythonからコンパイラを使うためには、ビルド環境が正しくセットアップされた端末エミュレータ上でPython(Cython)を走らせる必要がある。最もシンプルなのは
- Windows標準のシェルでpython環境が動くようにする
- Visual Studioのコマンドプロンプトを起動して、そこでpythonのsetup.pyを動かす
という方法だけれど、Anacondaの仮想環境を使いたい場合はとてもややこしい事態になるだろう。どこでどういう環境変数をセットアップすればanaconda prompt上で使えるようになるのか試行錯誤中…
インストール
pipを使えばすぐに終わる。確か管理者権限は必要なかったような気がする…。
$ pip install cython
コンパイルできるか確認
Cython: Basic tutorialのコードをそのままコピペして、コンパイルできるかチェックする:
- 開発用のディレクトリを作成。この中にファイルを作成していく。
- ".pyx"ファイルを作成。これがコンパイル元のコード。
- "setup.py"ファイルを作成。これがビルドファイルになり、コンパイルのされ方を指定する。
- 開発用ディレクトリ内で端末エミュレータを開き、
python setup.py build_ext --inplace
を実行。Windowsの場合、必要なコマンドやインクルードファイルを使うためにdeveloper command prompt上で行う必要がある。
setup.py
実行の際、--inplace
オプションをつけないと、あるいはPythonのライブラリーの方にインストールされてしまうやもしれない(未確認)。
コンパイルが成功すれば"Finished"的なメッセージとともにsetup.pyが終了する。その場合、pythonコンソール上でimport <pyxファイル名>
とすることでコンパイル済みファイルをインポートできる。
一方、コンパイルが失敗した場合、"Failed"的なメッセージが出てくる。端末エミュレータの出力の少し前に戻るとエラーのより詳細な内容がわかる。ほとんどの場合は.pyxファイルの記述間違いか、インクルード/リンクファイルが見当たらないというものだと思う。
ライブラリヘッダファイルの追加
Stack Overflowの解答よりコードを抜粋。
Cythonからnumpyを使ったりする場合、numpyライブラリのCヘッダファイル群が必要になる。gccやらを用いて直にコンパイルする場合はわかりやすいが、setup.py経由でコンパイルする場合は-I
オプションが使えない。
この場合、distutils
のExtension
オブジェクトを利用する:
from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
setup(
ext_modules=[
Extension("my_module", ["my_module.c"],
include_dirs=[numpy.get_include()]),
],
)
この場合の2つ目の引数は、ソースファイルのリスト(の絶対あるいは相対パス)を指定する。include_dirs
キーワード引数で、追加したいインクルードパスを列挙する。
あるいはCython documentationを見ると、cythonize()
そのものにinclude_dirs
というオプションがあるらしい:
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = "My hello app",
ext_modules = cythonize("src/*.pyx", include_path = [...]),
)
numpy
はget_include()
という関数を提供してくれているのでそれを使えばよいし、ネイティブのライブラリでもpkg-configなりなんなりの出力を使用すればよかろう。