pythonとc++のインターフェイスの比較 swig boost.python ctypes

pythonc++インターフェイスを作る方法には

  1. boost.pythonを使う方法
  2. swigを使う方法
  3. python.ctypesを使う方法
  4. f2py (Fortranを使うためのInterface)を使う方法
  5. pyreを使う方法
  6. 直接Cのインターフェイスを作る方法

があるようだ。
http://www.scipy.org/Cookbook のUsing NumPy With Other Languages のセクションにさらに詳しい解説がある。
 ここでは特に配列(numpyの行列)をc++と連携して使う方法に注目していくつかの方法を比較する。numpyは数値計算や行列演算を行うpythonのパッケージでnumarrayの後継にあたる。numpyはnumarayと違って行列が配列の先頭ポインター(double *array)を渡すだけでc++とやりとりができる。そのためc++との連携で様々なメリットがある。

 以下にも類似した比較等の議論がある

  1. http://tasuku.suenaga.name/pub/pytc/Python-unconference01-cextension.pdf
  2. http://language-binding.net/

boost.python

boost.pythonを使う方法はubuntu7.10の場合は $ sudo apt-get install libboost-python とすることで導入できる。使い方は以前ここ
http://d.hatena.ne.jp/niitsuma/20080108/1199769332
に書いた。この方法のメリットは

  1. pythonからc++呼べるだけでなく、逆にc++からpythonのprogramを呼び出せる. 以下は詳しい使い方を解説しているサイトへのリンク
    1. http://d.hatena.ne.jp/Wacky/20060103/1136292735 : boost.pythonだけでなくswigの解説もある。わかりやすいexample codeもある
    2. http://d.hatena.ne.jp/kikuty/20080110 : c++からpythonをboost.pythonで呼び出す方法の解説。関連するVisual Studioの設定の話題など。あまりわかりやくすない。
    3. http://www.boost.org/libs/python/doc/tutorial/doc/html/python/embedding.html boost本家の解説
    4. 関連
      1. http://wiki.python.org/moin/boost.python/EmbeddingPython 
      2. http://www.boost.org/libs/python/doc/v2/exec.html
      3. http://www.boost.org/libs/python/doc/v2/import.html
      4. http://www.boost.org/libs/python/doc/v2/callbacks.html
  2. c++のclassをpythonに渡せる
    1. http://python.matrix.jp/tips/cpp_extension.html
    2. http://www.boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html

デメリットは

  1. numpyにまだ対応していない
  2. c++のコードを改変しないといけない(boost.pythonのヘッダーを追加したりする)

がある。
boost.pythonインターフェイスを生成する作業を自動化するPy++というtoolもある。しかし試したところ、この自動化toolは複雑なc++のコードでは動かないようだ。
 現在のboostはnumarrayには対応しているがnumpyには対応していない。以下のサイトの方法でnumpyの配列(行列)をc++に渡すことができるらしいがubuntu7.10の環境では動かなかった。
http://www.eos.ubc.ca/research/clouds/software/pythonlibs/num_util/num_util_release2/
(誰か動かせた人がいたら環境の情報など教えていただけると幸せです)
boost.ublasのインターフェイスも書かれているようだ
http://mail.python.org/pipermail/c++-sig/2006-December/011719.html

swig

swigの生成するwrapperファイル hoge_wrapper.cとwrapしたいhoge.cを一緒にコンパイルするだけですむので、既存c++libraryをpythonに移殖するには向いていると思われる。しかし,少し複雑なc++のコードになると扱うことができない。(複雑なc++コードをwrapするために http://www.itk.org/HTML/CableSwig.html こんなものもあるようだ. cableswigについては別記事cable swigを書いた)
std::vectorなど様々なc++要素に対するインターフェイスが用意されている。c++のclassをpythonから呼ぶこともできる.classの呼び方は以下

  1. http://www.geocities.com/foetsch/python/extending_python.htm#example 短いexmaple codeで使い方がすぐわかる
  2. http://www.swig.org/Doc1.3/Python.html#Python_nn20 同じくswig本家の example code.こちらもわかりやすい.

boost.pythonと異なりc++から逆にpythonのコードは呼び出せない。
numpyに対応している。numpy/docs/swig にあるnumpy.iファイル(ubuntu7.10の場合は /usr/share/doc/python-numpy/swig/numpy.i.gz )を使ってhttp://projects.scipy.org/scipy/numpy/browser/trunk/numpy/doc/swig/doc/numpy_swig.html?format=raw の方法を実行すればよいらしい。swigの使い方はサンプルコードの通りにまねすればいいだけなので簡単だ。ただし計算速度が遅くなるとswigのサイトには書いてあった。googleではswigが使われているそうだhttp://www.atransia.co.jp/home/fukamachi/Diary/2006/02/12/

ctypes

c++から呼ぶためのdllやshared libをpythonからも呼んでしまう方法。boost.pythonと異なりc++から逆にpythonのコードは呼び出せない。swigと異なりcのコードに手を加えるのではなく呼び出すpythonの側でいろいろと手間を追加する方法だ。使い方を学習する手間はswigと同程度。(次versionのpythonであるpython3.0にもctypesはあるようだ )ctypes一般の使い方は以下のサイトが参考になるになる

  1. http://newcamel.logos.ic.i.u-tokyo.ac.jp/~s1s5/pukiwiki/index.php?programming%2Fpython%2Fctypes
  2. http://blog.goo.ne.jp/anoydevl/e/a1193ca3cafed036c8c232ac4a14d894 工夫してclassをctypsから呼ぶ方法
  3. ctypes tutorial

linuxの場合はこんな風に使う

import ctypes
libc = ctypes.cdll['/lib/libc.so.6']
name = "John Doe"
libc.printf("Hello, %s!\n", name) 

windowsの場合は,

from ctypes import windll
windll.user32.MessageBoxW( 0, u"テスト", 0, 0 )

のように使う.windowsの場合のより詳しい使い方は http://mtamaki.com/trac/mtamaki/ticket/47
以下のようにしてstructを扱うこともできるようだ.

struct svm_node {
    int index;
    double value;
};
from ctypes import Structure, c_int, c_double
class svm_node(Structure):
    _fields_ = [('index', c_int), ('value', c_double)] 

関数や構造体の呼び出しはできるがstd::vectorc++のclassをpythonから呼ぶ方法は見つけられなかった(ここで工夫してclassを扱う方法も解説している)。
 numpyも使える。numpyの行列(配列)を使う方法は
http://www.scipy.org/Cookbook/Ctypes
に書いてある。
OpenCVと組み合わせてnumpyも使う場合にswigとctypesのどちらが良いかの議論がここでされている。結論としてはOpenCVと組み合わせる場合はctypesがいいということのようだ。同様の使い方をctypesでする場合の話題がここにまとめられている。

直接cのインターフェイスを書く

http://projects.scipy.org/scipy/numpy/wiki/NumPyCAPI
に書いてる方法でできるようだ。

結論

boost.pythonがnumpyに対応してくれるなら一番うれしい.swigは複雑なコードを変換できないため手で修正する必要があるためおすすめできない。ctypesも良いがclassやstd::vectorを直接pythonから呼び出す方法をみつけられなかった。もしあるならばctypesを使いたい。次期バージョンのpythonであるpython3.0にctypesがあるので後のことを考えるとctypesもいいのかもしれない。