distutils with boost.python

昨日のエントリのコメントにて、

nishionishio『とりあえずインストールしてみたけどなにがいいのかよくわかんない…
bjamとかいう独自のビルドツールを使うせいで標準のdistutilが持っている機能(Windowsインストーラがコマンド1行で作れるとか)が使えなくなってしまっている気がする。』 (2007/06/11 12:33)

earth2001yearth2001y『bjamはboost自体をビルド、インストールするのに使うだけで、それ以後は関係ないよ。distuilも普通に使えるので、整理して新しいエントリに書きますね。』 (2007/06/11 18:46)

って書いたので、Boostの準備からモジュールの作成、インストールまで、順を追って書き出してみますた。

Boostをインストール

まず、Boostの準備。BoostのソースとbjamをBoostの配布元からとってくる。Boosy.Pythonはデフォルトではインストールされないので注意が必要。環境変数PYTHON_ROOTとPYTHON_VERSIONを設定してあげると、インストールされるよ。

% cd boost_1.33.1
% export PYTHON_ROOT=/usr/local
% export PYTHON_VERSION=2.4
% sudo bjam --prefix=/usr/local install

FreeBSDportsからBoostをインストールするときは、WITH_PYTHON=yesをつけてあげればいい。

% cd /usr/ports/devel/boost
% sudo make WITH_PYTHON=yes install clean

これでBoostは準備完了。これ以後はbjamは使わないので、bjamの存在は忘れ去ってOK。

モジュール本体

つづいて、C++でモジュール本体を記述。Boost.Pythonを使う理由はこれが簡単に書けること。普通に関数を書いて、Pythonへエクスポートする関数を列挙すればいいだけ。PythonのSDKを使って書くのと比べればかなりシンプル。

/* foo.cpp */
#include <boost/python.hpp>
#include <string>

std::string hello() // 関数本体
{
    return "Hello, Boost Python!";
}

BOOST_PYTHON_MODULE(foo)
{
    boost::python::def("woo", hello); // エクスポート!
}

setup.py

続いて、setup.pyを用意。このとき、Boost用にインクルードパス、ライブラリパスを設定し、libboost_python.aをリンクすることを忘れないように。インストール時の環境によっては、libboost_python.aが、libboost_python-***.a(***はコンパイラ、ビルドバージョンの符号)になっていることがあるので、確認しておこう。

#!/usr/bin/env python
# setup.py
from distutils.core import setup, Extension

module = Extension(
    'foo',
    sources = ['foo.cpp'],
    include_dirs = ['/usr/local/include/boost_1.33.1'], # boostのインクルードディレクトリ
    library_dirs = ['/usr/local/lib'],                  # boostのライブラリディレクトリ
    libraries = ['boost_python']                        # libboost_python.aをリンクする
)

setup(
    name = 'boo',
    version = '0.01',
    ext_modules = [module],
)

インストール、実行

あとは、setup.pyを使ってモジュールをビルド、インストールするだけだ。

% python setup.py build
% sudo python setup.py install
>>> import foo
>>> dir(foo)
['__doc__', '__file__', '__name__', 'woo']
>>> foo.woo
<Boost.Python.function object at 0x30a050>
>>> foo.woo()
'Hello, Boost Python!'

てな具合。

MacFreeBSD上で作業をやっているのでWindowsインストーラ作成云々は分からない。でも、ちゃんとdistutilsを使っているので、Windowsインストーラ作成もできると思う。