LoginSignup
36
36

More than 5 years have passed since last update.

C++でpythonを拡張する(Boost.NumPy)

Posted at

何故C++のクラス・関数をPythonにバインドするか?

C++11は非常に便利になった。Boost使えばさらに便利だ。
しかし、pythonはもっと使いやすい。
NumPyをベースにしたプロジェクト群(SciPy, matplotlib, pandas, ...)
は共通の基盤の上に非常に使い易く整備されている上に、そこそこ高速に動作する。
C++を使うべきか、Pythonにバインドして使うべきか、
また私の中で結論はでていないが、とりあえずバインドするための情報をまとめる。

どうやってバインドするか?

問題は2つある。

  • 単純にPythonにバインドする方法
  • NumPyにバインドする方法

Pythonを使う理由の一つにNumPyのベースのライブラリを使用する事があるので、
NumPyのndarray等に変換できる必要がある。

基本となるのはPython C APINumPy 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
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);
}

こんな感じで書く。かなり直感的に書ける。

CMakeLists.txt
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だったりするので注意する。

もっと詳しい使い方は次回。

36
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
36