はじめに
Pythonは書きやすいけど速度が残念…
ということで、一部をC++で書き直してPythonから呼び出そうとしたんですが新しめの情報が少なかったのでまとめておきます。
Cythonを利用しますが、Cythonの導入やC++のコンパイラの導入などは解説しないので、他記事を参照してください。
例としてC++で足し算を行うadd_cという関数を作り、それをPythonから使ってみます。
C++側
Pythonから使うために特別な書き方をする必要はなく普通に書きます。
calc_c.hpp
#ifndef __GUARD
#define __GUARD
int add_c(int x, int y);
#endif
calc_c.cpp
#include "calc_c.hpp"
int add_c(int x, int y){
return x + y;
}
Python側
直接PythonからC++の関数を呼ばずに、Cythonを経由して型の情報をつけてからC++の関数を呼びます。
calc.pyx
cdef extern from "calc_c.hpp": #使いたい関数を含むC++のヘッダーを指定する
cdef int add_c(int x, int y) #使いたい関数を宣言する
#C++の関数を型情報をつけて呼び出すラッパー関数
def add(int x, int y):
cdef int ans
ans = add_c(x, y)
return ans
コンパイル
calc.pyxをコンパイルするための設定ファイルを書きます。
setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
#コンパイルするソースファイルをリストで指定
source = [
'calc_c.cpp',
'./calc.pyx'
]
setup(
cmdclass = dict(build_ext = build_ext),
ext_modules = [
Extension(
'calc', #この名前でimportできるようになる
source,
language='c++', #C++でコンパイルするために必要
)
]
)
以下のコマンドを実行するとコンパイルが実行されて、共有ライブラリ(拡張子:so)ができます。
$ python3 setup.py build_ext
使ってみる
コンパイルして作った共有ライブラリを同階層に置いておけばimportで読み込めます。
main.py
import calc
print(calc.add(1, 1))
注意
C++側の関数名とCython側の関数名が被っているとコンパイルに失敗します。