何故C++のクラス・関数をPythonにバインドするか?
C++11は非常に便利になった。Boost使えばさらに便利だ。
しかし、pythonはもっと使いやすい。
NumPyをベースにしたプロジェクト群(SciPy, matplotlib, pandas, ...)
は共通の基盤の上に非常に使い易く整備されている上に、そこそこ高速に動作する。
C++を使うべきか、Pythonにバインドして使うべきか、
また私の中で結論はでていないが、とりあえずバインドするための情報をまとめる。
どうやってバインドするか?
問題は2つある。
- 単純にPythonにバインドする方法
- NumPyにバインドする方法
Pythonを使う理由の一つにNumPyのベースのライブラリを使用する事があるので、
NumPyのndarray
等に変換できる必要がある。
基本となるのはPython C APIとNumPy C APIである。
これらを通してC++の関数やクラスをPythonにバインドする。
C++は当然Python C APIを直接呼びだせるが、
参照カウントを自分で制御しないといけない。
これは無理ゲーすぎるので、その辺をC++らしくラップしたのがBoost.Pythonである。
スマートポインタで参照カウントは管理してくれる。
一方で、NumPy C APIはPython C APIとは別物であるため、
Boost.Python自体にはNumPyのAPIのラッパーは含まれていない。
そこでBoost.PythonをベースにNumPyのためのインターフェイスを
実装したものがBoost.NumPyである。
現在Boost sandboxに入ってると書いているが、
Boost本体の開発がGithubに移ってからSandboxは運用されていないようだ。
開発はgithubで行われている。
Boostとしての立ち位置はよく分らない。
Install
git clone https://github.com/ndarray/Boost.NumPy
cd Boost.NumPy
した事前提で話を進める。
documentのビルド
cd libs/numpy/doc
make
としてlibs/numpy/doc/_build/html/index.html
を開けばドキュメントが見れる
cmakeによるインストール
上述のドキュメントに詳しくある(略)
python3環境でコンパイルするには少し変更が必要となる。
使い方
SciPyの各種アルゴリズムを使うためには
numpy.ndarray
を引数にして同じndarray
を返す関数が必須。
NumPyの肝であるndarrayをC++で作る
project/CMakeLists.txt
numpy.cpp
#include "boost/numpy.hpp"
namespace p = boost::python;
namespace np = boost::numpy;
np::ndarray new_zero1(unsigned int N) {
p::tuple shape = p::make_tuple(N);
np::dtype dtype = np::dtype::get_builtin<double>();
return np::zeros(shape, dtype);
}
BOOST_PYTHON_MODULE(mymodule) {
Py_Initialize();
np::initialize();
p::def("new_zero", new_zero1);
}
こんな感じで書く。かなり直感的に書ける。
cmake_minimum_required(VERSION 2.8)
# set(CMAKE_VERBOSE_MAKEFILE 1)
find_package(Boost COMPONENTS python3 REQUIRED) # for python3
find_package(PythonLibs REQUIRED)
include_directories(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
add_library(mymodule SHARED numpy.cpp)
target_link_libraries(mymodule ${Boost_LIBRARIES} ${PYTHON_LIBRARY} boost_numpy)
set_target_properties(mymodule PROPERTIES PREFIX "") # 接頭辞'lib'を省略するため
cmake .
make
これでmymodule.so
ができる。
set_target_propertiesを書かないとlibmymodule.so
となる。
LIBRARYだったりLIBRARIESだったりするので注意する。
もっと詳しい使い方は次回。