Boost.PythonおよびBoost.NumpyをWindowsで使うまで

5 Comments

こんにちはtatsyです。

C++とPythonを糊付けするものとしてBoost.PythonとBoost.Numpyというものがあるのですが、多くの記事はPythonからC++のコードを呼び出すことを主眼としていて、僕のようにC++からNumpyの線形ソルバーを呼びたいとか言う人は少ないみたいです。

Boost.PythonやBoost.Numpyを使う利点、特にWindows上で使う利点はPythonをビルドしているVisual Studioのバージョンに依存しないということだと思います。

通常PythonのC APIは使っているPythonをビルドしたものと同じVisual Studioのバージョン(3.4ならVC2010, 3.5ならVC2015)を使ってビルドしないといけないので、いちいち複数のバージョンのVisual Studioを入れないといけなかったりします。

参考ページ: Windows での Python 2.7/3.4 の拡張モジュールビルド環境

というわけで、今回は、Boost.Numpyを使ってC++からサクサクと連立一次方程式を解くまでをインストールから順に解説していきたいと思います。

今回、実験した環境は

  • Windows 7 64 bit
  • Visual Studio 2015
  • Python 3.4
  • Boost 1.59.0

です。
 

Python, Numpyのインストール


Pythonは本家のサイトからお好きなバージョンを落としてください。今回の記事では私がPython3系を使っていることもあって、3系のための解説になってしまいますのでご了承ください。

次にNumpyですが、pipとかだと環境によってビルドが通らなかったりするので、おとなしく非公式アーカイブからNumpyをいただいてきます。

こちらで配布されている.whlファイルを

のように呼んであげると、インストールできます。
 

Anacondaを使う場合

AnacondaあるいはMinicondaの環境でBoost Numpyを使いたい場合には少し工夫が必要です。ここでは新しくBoostという仮想環境を作る前提で話を進めます。

まず、仮想環境を作り、そこにPython(ここでは3.5)とNumpyをインストールします。

そうすると(Anacondaのディレクトリ)/envs/Boostというディレクトリがこの仮想環境でのPythonのホーム・ディレクトリになります。

通常のPythonのインストールの際には必要ないのですが、仮想環境を使う場合には、Pythonのホーム・ディレクトリとライブラリのディレクトリを環境変数に追加してあげる必要があります。

変数名: PYTHONHOME
値: (Anacondaのディレクトリ)/envs/Boost

変数名: PYTHONPATH
値: (Anacondaのディレクトリ)/envs/Boost/DLLs;(Anacondaのディレクトリ)/envs/Boost/Lib;(Anacondaのディレクトリ)/envs/Boost/Lib/site-packages

これで以下は通常のPythonと同じ設定でBoost.Pythonが使えるようになります。
 

Boostのインストール


まずはBoostのサイトにアクセスをしてBoostの最新バージョン(2015年11月6日現在)である1.59.0をダウンロードしてきます。

そうしたら、Lhaplusか何かでzipやtar.gz等を解凍します。するとboost_1_59_0というフォルダができるので、これを適当な場所に置きます。

僕は「C:/Libraries/boost_1_59_0」に配置していますので、以下はその前提でいきます。

そうしたら、Boostフォルダのルート・ディレクトリにあるbootstrap.batをコマンド・プロンプトから実行します。

数分くらい時間がかかると思いますが、そうすると同じくルート・ディレクトリにbjam.exeb2.exeという実行ファイルが出来ると思います。

僕の環境で実行した結果はこんな感じになりました。

boost_folder

 

Boost.PythonおよびBoost.Numpyのビルド


先ほど作成したb2.exeを使うとBoostに初期状態から同梱されているBoost.Pythonはビルド可能です。

Boost.Numpyは同梱されていないのでGitレポジトリから落としてきて、一緒にビルドできるように設定します。まずはBoost.NumpyのレポジトリをCloneしてきます。

Cloneしてきたフォルダの中にはいくつかのファイルとフォルダが含まれていますが、この中で重要なのはboostlibsというフォルダです。この2つのフォルダをコピーして、Boostのルート・ディレクトリでペーストします。

次に、b2でビルドするためにいくつかの設定を行います。まず、(Boostのルート)/libs/numpyにあるsrcというフォルダをbuildという名前に変更します。これはBoostに同梱されているビルドスクリプトが(Boostのルート)/libs/(パッケージ名)/build/Jamfileというビルド・スクリプトを使ってビルドしているためです。

続いて、今名前を変更したbuildフォルダの中にあるJamfileをエディタで開いて、1点変更をします。

変更前

変更後

ここでは、Boost.NumpyについているJamfileがPython2風に書かれているので、それをPython3風に変更しています。
 

ここまで出来たら、いよいよビルドです。コマンドは単純で、

です。なお、僕の環境は64ビットでしたのでaddress-modelを64にしていますが、32ビットの場合には、この数字を32に変えればOKです。

なお、-j2は並列コンパイルに使うCPUコアの数を–prefixはBoostのルート・ディレクトリを指定するのに使います。今回はBoostのルート・ディレクトリで上記のコマンドを実行しているので、ドット1つになります。

コマンドを実行後10数分待つと、ビルドが完了するはずです。

注) 一応Boost.NumpyにはCMakeのファイルが付いているのですが、これを使ってビルドするとマルチスレッドとマルチスレッド・デバッグの間でライブラリの競合が起こってリンクできないという問題が発生したため、今回は他のライブラリと一緒にb2でビルドします。
 

Boost.Numpyを使ってC++から関数を呼び出す


ライブラリのインストールが終わったところで、次は自分のプログラムからBoost.Numpyを使ってNumpyの関数を呼び出します。

まず、ビルドをするためにVisual Studioのプロジェクトを作ります。プロジェクトが出来たら、プロジェクトのプロパティから「構成プロパティ」→「VC++ディレクトリ」を開き、以下の変更を施します。

インクルード ディレクトリに以下を追加。

  • C:/Python34/include
  • C:/Libraries/boost_1_59_0 (Boostのルートディレクトリ)

ライブラリ ディレクトリに以下を追加。

  • C:/Python34/libs
  • C:/Libraries/boost_1_59_0/lib

続いて、「リンカー」→「入力」を開いて、「追加の依存ファイル」に以下のライブラリを追加します。

  • Python34.lib
  • libboost_numpy-vc140-mt-1_59.lib (Releaseの場合)

 

これでインクルードとライブラリの設定は完了です。次にコードを書きます。今回、書いたコードは以下のような感じです。

いくつかポイントを解説します。

1行目

BOOST_PYTHON_STATIC_LIBというマクロは、Boostのライブラリを静的にリンクすることを明示するものです。これをつけないとDLLに依存した実行ファイルが出来てしまうそうです。

12, 13行目

これはPythonおよびNumpyを使うための諸々の初期化をやってくれる関数です。呼ばないと実行時エラーになるので注意してください。

16行目

Boost.Numpyの現在の実装では、std::tupleなどをサイズとして渡せないので、boost::python::tuple型のサイズを示すtupleを作っています。

17行目

見ての通りですが、要素が全て0の2次元配列を作っています。

18-21行目

単に要素を入れているだけです。このようにかなり直感的な書き方ができるのは嬉しいです。

24-27行目

行列の作成と同じようにしてベクトルを作っています。

30行目

呼び出す関数を用意しています。

33行目

関数を呼び出して連立方程式を解いています。戻り値はboost::python::object型なので、それをboost::numpy::ndarray型に変換しています。

36行目

結果を表示するために要素をdouble型として取り出しています。

実行結果

はい、きちんと計算できています。
 

まとめ


今回はBoost.PythonおよびBoost.Numpyを使ってC++からPythonの関数を呼び出してみました。

以前、通常のC APIをラップしたクラスを自前で作っていたのですが、その時はメモリ関係の謎のクラッシュに度々悩まされていたので、Boost.Python、Boost.Numpyは偉大だなと思います。

またWindowsでPythonのInteropをするときにVisual Studioのバージョンを気にしなくてもいいというのもありがたいです。

というわけで、今回の記事はこれで終わります。もし、上手くいかないなどの問題がありましたらコメントいただけると嬉しいです。

最後までお読みいただきありがとうございました。

5 thoughts on “Boost.PythonおよびBoost.NumpyをWindowsで使うまで

  1. 大変参考にさせていただきました。ありがとうございます。

    1点気付いたことがあったので、ご報告します。
    tatsy さんは、デフォルトの環境に numpyをインストールされていましたが、私の場合、Anacondaの仮想環境に numpy を使用していたため、b2 によるビルドの段で、numpy/arrayobject.h の file not found のエラーでコンパイルにつまずきました。

    注意書きとして、

    – ビルド中のプロセスで numpy本体のヘッダーも参照されていること (調べていませんが、numpy.get_include() などで .h の位置を探しているのでしょう)
    – 仮想環境のnumpyを使う場合には、b2 による ビルドの前にコマンドプロンプトで、その仮想環境をactivate しなければいけないこと

    など追加されると、後から見られるかたがよりスムーズに環境が導入できるようになるかな、と思います。

    ご参考まで。

    • kyokkeさん

      コメントいただきありがとうございます。
      Anacondaを使うということは記事を書いた当初は意識しておりませんでしたので、ご指摘を大変ありがたく拝見いたしました。

      早速、私の手元でテストをしてみたところ、Anacondaを使う場合も、そうでない場合もWindowsがPythonのインタプリタを環境変数のパスから探せるかどうかが大事なようでした。

      差し支えなければkyokkeさんの実行環境などをお教えいただけますと、私の方でもそれに合わせて補足をつけられるかと思います。

      いずれとしましても貴重なコメントありがとうございました。

    • Tatsy さん メールでのご返信ありがとうございました。
      コメント欄にてお返事さしあげます。

      1) Boost.Numpy を試した私の環境は下記の通りです。

      – windows 10 Pro 64bit
      – MSVC 2013 community edition
      – boost ver. 1.60
      – Miniconda3 (64bit)を chocolatey 経由でインストール
      – デフォルトのインストールパスは c:\tools\Miniconda3 のようです。

      この状態で、下記の仮想環境 “testenv” をconda コマンドで作成しました。

      > conda update conda # 最新版にアップデート
      > conda create –name=testenv python=3.4 numpy=1.10.1 # 現在主に使用中のバージョンを指定

      2) 私なりの解決方法

      ビルド時にnumpy本体のヘッダーが参照できない問題については、上でコメントした通り、

      > activate testenv
      とすることで、 b2.exe でのビルドを行う事で解決しました。

      また、Boost.Numpyを使った tatsy のサンプルコードをそのまま実行すると、私の環境では、numpy系のモジュールのimport error が発生してしまうため、

      Py_Initialize() 関数のよりも前で、
      Py_SetPythonHome(L”c:\tools\Miniconda3\envs\testenv\”)

      としてやることで、解決しました。

      特に一つ目の問題については、私自身 boost のビルドツールやディレクトリ構造に明るくないため、適当に解決してしまいましたが、おそらくは、bjamの設定ファイルや、コンパイル時のオプションとしてpythonのパスを明示的に指定するような解決方法もあるのだろう、と予想しています(あくまで予想。まったくの未調査です)

      • kyokkeさん

        詳細な実行環境をご教授いただき、ありがとうございます。
        仮想環境を通してPythonを触ったことはなかったのですが、
        確かに導入が一筋縄ではいかなさそうですね。

        まだ自分の方でチェックができていないのですが、いくつかの仮想環境上で
        実行するにはどうすればよいのか、自分でも少し調べてみたいと思います。

        このような問題は私一人では気づけなかったのと思うので、本当にありがたいです。
        貴重なコメントありがとうございました。

        P.S. テーマの関係でコメントが1つしか表示されていなかったみたいですね。

        • tatsy さん

          お返事ありがとうございます。もし私もよい解を思いついたらお知らせしますね。
          テーマ変えてくださったみたいで、コメントがみられるようになりました。
          こちらも迅速なご対応ありがとうございました!

          引き続きブログでの活動応援しています!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です