boost::pythonを使ってC++のPythonラッパーを作る

最近コーディングにはC++をメインに使っているのだけれど,軽いを処理はやっぱりスクリプト言語の方が楽.以前はラッパーを作るのにSWIGを使ったことがあるけれど,インタフェースファイルを用意するのにだいぶ苦労したので手軽にラッパーを書ける感覚がなかった.Boost本 (Boost C++ Librariesプログラミング第2版) を眺めていたら「boost::python」というページがあって,かなり手軽にPythonラッパーが書けそうな気がしたので試してみたのでメモ

こんな感じのコードを用意する.

#include <string>
#include <boost/python.hpp>

std::string
add_hello (std::string s)
{
  return "Hello, " + s;
}

int
square (int n)
{
  return n * n;
}

BOOST_PYTHON_MODULE (bpy)
{
  boost::python::def( "greet", add_hello );
  boost::python::def( "square", square );
}

ここでbpyという部分がモジュール名になる.def関数でPython側のメソッド名を定義している.あとはこれをコンパイルして共有ライブラリにするだけ…とboost本には書いてあるのだけれど,肝心なこの部分が一切書かれておらず少し苦労した.ハマったのは,以下の3点

  • Python.hが必要なので (Debina系の場合) aptを使ってpython-devをインストールしておく必要がある.
  • コンパイル時にインストールされたPython.hまでのヘッダファイルパスを指定する必要がある.
  • リンク時にlibboost_python.soを指定する必要がある.(自分の環境ではなぜかlibboost_python-mt.soという名前だった)

以上をふまえた共有ライブラリの作成コマンドは以下のとおり (1行にまとめてもよい)

% g++ -fPIC -I/usr/include/python2.6 -c bpy.cpp
% g++ -lboost_python-mt -shared -o bpy.so bpy.o

あとはpython側で動作確認

% python
Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bpy
>>> bpy.greet("hoge")
'Hello, hoge'
>>> bpy.square(5)
25

おぉ,ちゃんと動いた! 今回の例ではstring型とint型のみだけれど,クラスのラッパーも簡単に書けるっぽい.最近は世の中の流行に乗れるように? たまにPythonでコードを書くようにしている.ラッパーが書きやすいから,という理由でPythonに乗り換えられるといいのだけれど.

参考文献