MacOSX10.5のPython2.6で動かせる簡単なPyCXXの例を、貼り付けておきます。
test.cxx
mac_py26.mak
どちらも、サンプルファイルをちょっと変更してわかりやすくしただけですが、これだけで結構Py::Listの動きなどよくわかると思います。 ~/pycxx-6.1.1$ make -f mac_py26.mak で、test.soができていることを確認して、インタラクティブシェルを起動します。 ~/pycxx-6.1.1$ python Python 2.6.3 (r263:75184, Oct 2 2009, 07:56:03) [GCC 4.0.1 (Apple Inc. build 5493)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> >>> import test >>> l = test.func(range(3),10) 10.0 >>> l [0, 1, 2, 10.0] >>> type(l) <type 'list'> >>> という具合に使えます。 C++でコードを書くとき、ラッパーオブジェクトをどのあたりまで使ったらいいのかとか、本格的なプログラミングには、すこし考えが必要ですかね。 |
最近よく使っているRandom ForestsやNMF(non-negative matrix factorization)などの単純な繰り返し計算が多いアルゴリズムを実装すると、どうしてもPythonでは満足な実行速度が得られません。そういうときは、C++を使うんですが、タブ区切りのデータファイルを読み込んで2次元配列にするとか、そういう処理はC++じゃなくて、Pythonで書きたいわけです。
これまでも、PyscoやPyrexでの高速化を試してきたわけですが、やっぱりC++で書いたモジュールを >>> import hello >>> hello.foo() などとして使えると、かっこいいなーと思い、C++でPythonを拡張する方法をいくつか試してみました。 日本語でも詳しいページがいくつかあって、こちらはその代表格です。 Boostはよく使うので、Boost.pythonの存在は知っていて、Boostというブランドイメージもあり、良いものに違いないと思い、使って見ましたが、私にはどうもうまく使いこなせませんでした。簡単なC++のモジュールもMacOSXの環境でコンパイル出来ません。 そもそもbjamの使い方がわからないのですが、これに関しては同じことを言っている人がいらっしゃって、makeファイルを公開してくれています。いろいろいじって、コンパイルは通るようになったけど、インタラクティブシェルでimportするとエラーになったりと、どうにもこうにもうまく動かせる気配がなく、あきらめムードが漂ってきました。 やっぱり、SWIGか?と思い、こちらも試してみることに。SWIGは様々な言語からC/C++へのアクセスを可能にする仕組みで、とくにPythonとは相性がよいようです。こちらがもっとも簡単な紹介ページのようですが、なんか気に入りませんでした。いや、きっと良いものなんだろうと思うんですが、どうもしっくりきません。 ctypesは、Pythonに標準で装備されている機能なので、良いのでしょうが使い方が不格好過ぎてやる気が出ません。きっと、これは既存のC/C++で書かれたライブラリをそのままPythonで使うための手段でしょう。必要な部分だけをC++で作るという今回の目的とは少しずれているので、見送りです。 そうこうしていると、PyCXXなるものを見つけてしまいました。Googleで探してもあまり関連情報や紹介記事が無く、大丈夫なのかこれ?と疑ったりもしましたが、結局これをしばらく使ってみることにしました。どうやらPythonCライブラリをC++へ拡張したもののようで、まあ何より最初の導入がエラー無くうまく行ったのが採用の最大の理由です。 最新のバージョンは、6.1.1ですが、これをダウンロードし、解凍します。pycxx-6.1.1ディレクトリに移動するとREADME.htmlがありますので、指示に従ってください。 Python2.6が入ったMacOSXでは、sudo python setup.py installでインストールした後、 ~/pycxx-6.1.1$ make -f example_mac_py26.mak example.so としてモジュールをコンパイルした後、Pythonインタラクティブシェルを起動しモジュールをimportします。 >>> import example range object created 0xa16930 range object destroyed 0xa16930 >>> dir(example) ['__doc__', '__file__', '__name__', '__package__', 'a_constant', 'kw', 'range', 'string', 'sum', 'test'] >>> example.test() Example Test starting Trying to convert a NULL to an Py::Int Correctly caught Py::Exception value: PyCXX: Error creating object of type N2Py6ObjectE from (nil) Py::Exception traceback: None 以下省略 などと、動きます。 あとは、Demo/Python2/example.cxx を見ながら適当に改変するなり、コピーして自分のモジュールを作ればOK。 Pythonのオブジェクトをスマートにラップしてくれているので、少しさわってみた感触では、とっても使いやすそうです。 Boostでの拡張モジュールのビルドには苦しめられ続けたので、きっとPyCXXの方が簡単なんじゃないかなーと思っていたら、ここに投稿しているlucさんも同じようなことを言っていて、PyCXXの知名度がもう少しあがってもいいんじゃないかなーと思っています。かなりお勧めです。 |
| ホーム |
|