swigで pythonとc++連携
pythonやjavaが遅いのなら その部分だけ別の言語で書けばよいではないか という拡張の話
参考にしたページは以下
SWIG and Python
http://www.swig.org/Doc1.3/Python.html
distutils with boost.python - おびなたん☆
http://d.hatena.ne.jp/earth2001y/20070611/p1
C++とPythonのコラボレーション ― PythonMatrixJp
http://python.matrix.jp/tips/cpp_extension/
nesugi.net - swigの使い方のメモ書き
http://www.nesugi.net/hiki/?swig%A4%CE%BB%C8%A4%A4%CA%FD%A4%CE%A5%E1%A5%E2%BD%F1%A4%AD
手順は以下
hello.cpp, hello.h hello.i setup.pyを用意する
swig -c++ -python hello.i
で
hello_wrap.cxx とhello.pyが生成される
python setup.py build_ext --inplace
でc++プログラムがビルドされ
カレントディレクトリに_hello.soが
また build/temp.macosx-10.6-universal-2.6/以下に
hello.oとhello_wrap.o
が生成される
>>> import hello >>> dir(hello) ['MyClass', 'MyClass_swigregister', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_hello', '_newclass', '_object', '_swig_getattr', '_swig_property', '_swig_repr', '_swig_setattr', '_swig_setattr_nondynamic', 'get_sine', 'hello', 'new', 'new_instancemethod', 'sum'] >>> hello.hello() Hello World!! >>> a=hello.sum(5) >>> a 10 >>> a=hello.MyClass("this is a class.") >>> a <hello.MyClass; proxy of <Swig Object of type 'MyClass *' at 0x21efa0> > >>> dir(a) ['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__swig_destroy__', '__swig_getmethods__', '__swig_setmethods__', '__weakref__', 'a', 'clear', 'name', 'set_a', 'set_name', 'size', 'this'] >>> a.name() 'this is a class.' >>> a.set_name("we are the world") >>> a.name() 'we are the world'
ということで クラスやSTLもきちんと使える
hello.cppをいじったらリビルドするだけでなくpythonは再起動しなければならない
reloadしても中身が更新されないので注意
hello.cpp
#include "hello.h" #include <cstdio> #include <cmath> void hello(void) { printf("Hello World!!\n"); } int sum(int d) { int ret=0; for (int i=0;i<d;++i) { ret += i; } return ret; } double get_sine(int size) { const double width = 2 * M_PI/(double)size; printf("size = %d, width = %e\n",size,width); double sum = 0.0; for (int i=0;i<size;++i) { double x = i * width; sum += sin(x); } return sum; } MyClass::MyClass(const std::string& name) : a_(0),name_(name) { } void MyClass::set_a(int a) { a_.push_back(a); } int MyClass::a(int d) const { if (d>=a_.size()) { return 0; } return a_[d]; } void MyClass::clear() { a_.clear(); } int MyClass::size() const { return a_.size(); }
hello.h
#include <vector> #include <string> class MyClass { public: MyClass(const std::string& name); void set_a(int a); int a(int d) const; void clear(); int size() const; void set_name(const std::string& name) { name_= name;} const char* name() const {return name_.c_str();} private: std::vector<int> a_; std::string name_; };
hello.i
%module hello
%include "std_string.i"%{
void hello(void);
int sum(int d);
double get_sine(int size);
#include "hello.h"
%}
void hello(void);
int sum(int d);
double get_sine(int size);
%include "hello.h"
setup.py
%module hello %include "std_string.i" %{ void hello(void); int sum(int d); int sum2(int d); double get_sine(int size); #include "hello.h" %} void hello(void); int sum(int d); int sum2(int d); double get_sine(int size); %include "hello.h"