Cython による C / C++ モジュールの作成#

Cython は Python 風の記述で C / C++ によるモジュールを作るライブラリ。

静的に型を指定することができるため、 Python では遅くなりやすい演算を C 言語の速度で行うことが可能となる。

インストール#

pip コマンドなどで cython パッケージをインストールする。

Jupyter における使用方法#

このページは Jupyter で作成しているため、ここでは Jupyter で Cython を使用する方法を説明する。

まず、以下の記述により Cython を有効化する。

%load_ext Cython

続いて、%%cython から始めるセルで対象となる処理を実装する。

%%cython

# 演算が重くなりやすい例として、良くないアルゴリズムでフィボナッチ数列を計算してみる。

cpdef int fibonacci(int number): # 静的な型はアノテーションでなく C 言語風に前に書く。
    if number < 2:
        return 1
    return fibonacci(number - 1) + fibonacci(number - 2)

Hint

%%cython のセルの中は Cython 独特の記述方法が混じった Python 風の言語で記載する。

%%cython の記述をした関数は同じ Jupyter のファイルからは通常の Python と同様に呼び出せる。

fibonacci(10)
89
fibonacci(20)
10946
fibonacci(30)
1346269

記述例#

以下では色々な関数を記述してみる。 詳しい書き方は Cython のドキュメントを参照。

C 言語の関数の呼び出し#

%%cython

# 試しに C 言語標準ライブラリの中の strlen 関数をあえて Python から呼んでみる。

# 呼び出す対象の関数の宣言を書く。
cdef extern from "string.h":
    size_t strlen(const char* string)

# C 言語の関数をラップして Python から呼べるようにする。
def c_strlen(str string):
    """C 言語の strlen 関数で文字数を取得する関数。"""
    return strlen(string.encode("utf-8"))
c_strlen("abc")
3
c_strlen("テスト")
9

C++ の機能の利用#

%%cython

# distutils: language = c++
# 上記の行がないと C++ の機能が使用できない。

# C++ 標準ライブラリの std::string を読み込む。
from libcpp.string cimport string

def cpp_str_len(str s):
    """C++ の std::string::size 関数で文字数を取得する関数。"""
    cdef string cpp_str = s.encode("utf-8")
    return cpp_str.size()
cpp_str_len("abc")
3
cpp_str_len("テスト")
9

配列の利用#

%%cython

def sum_in_cython(double[:] values):
    """Cython でリストの総和を求める。"""
    cdef double sum = 0
    for value in values:
        sum += value
    return sum
import numpy

sum_in_cython(numpy.array([1, 2, 3], dtype=numpy.float64))
6.0

Important

通常の list 型のデータを使用すると

TypeError: a bytes-like object is required, not 'list'

のようなエラーになって実行に失敗する。