SWIGはC/C++で書いたプログラムをRubyから呼び出せるようにするためのツールです。SWIGを使えば、全体はRubyで書き、特にパフォーマンスが要求される部分だけをC/C++で書くといったことが可能になります。
環境
環境は以下のとおりです。- Mac OS X 10.6.6
- Ruby 1.8.7 p334
- gcc 4.2.1
- SWIG 2.0.3
SWIGのインストール
MacならMacPortsを使って簡単にインストールできます。
$ sudo port install swig
Rubyの拡張ライブラリを作るには、いっしょにRubyバインディングもインストールする必要があります。
$ sudo port install swig-ruby
サンプルプログラム
簡単なサンプルとして、C言語で書いたフィボナッチ数列を計算するプログラムを拡張ライブラリ化してみます。ソースコートは以下のとおりです。
fib.c
fib.h
まずSWIG用のインタフェースファイルを書きます。インタフェースファイルには、モジュール名とモジュールから呼び出す関数を宣言します。
fib.i
インタフェースファイルが書けたらswigコマンドを実行します。swigコマンドを実行すると、C言語の関数をRubyから呼び出すためのラッパーファイルを生成してくれます。
ここまででSWIGの仕事は終わりです。
最後にソースファイルとラッパーファイルを使って共有ライブラリを作ります。Makefileを自分で書くのは面倒なので、extconf.rbに生成してもらいましょう。
extconf.rb
C言語の関数をRubyから呼び出してみます。共有ライブラリをrequireすれば、通常のモジュール関数のように呼び出すことができます。
bench_fib.rb
結果は以下のようになりました。やっぱりC言語は速い!
int fib(int n) { if (n == 0) { return 0; } if (n == 1) { return 1; } return fib(n - 1) + fib(n - 2); }
int fib(int n);
まずSWIG用のインタフェースファイルを書きます。インタフェースファイルには、モジュール名とモジュールから呼び出す関数を宣言します。
fib.i
%module fib extern int fib(int n);
インタフェースファイルが書けたらswigコマンドを実行します。swigコマンドを実行すると、C言語の関数をRubyから呼び出すためのラッパーファイルを生成してくれます。
$ swig -ruby fib.i
ここまででSWIGの仕事は終わりです。
最後にソースファイルとラッパーファイルを使って共有ライブラリを作ります。Makefileを自分で書くのは面倒なので、extconf.rbに生成してもらいましょう。
extconf.rb
require 'mkmf' create_makefile("fib")
$ ruby extconf.rb $ make
C言語の関数をRubyから呼び出してみます。共有ライブラリをrequireすれば、通常のモジュール関数のように呼び出すことができます。
irb(main):001:0> require 'fib' => true irb(main):003:0> puts Fib.fib(10) 55 => nilおー。無事呼び出せましたね。
ベンチマーク
ベンチマークを測定し、Rubyで書いたプログラムとパフォーマンスを比較してみました。bench_fib.rb
#!/opt/local/bin/ruby require 'fib' require 'benchmark' def fib(n) return 0 if n == 0 return 1 if n == 1 fib(n - 1) + fib(n - 2) end n = 30 Benchmark.bm(13) do |x| x.report("c fib(#{n}):") { Fib.fib(n) } x.report("ruby fib(#{n}):") { fib(n) } end
結果は以下のようになりました。やっぱりC言語は速い!
user system total real c fib(30): 0.010000 0.000000 0.010000 ( 0.015184) ruby fib(30): 2.170000 0.000000 2.170000 ( 2.176323)
0 件のコメント:
コメントを投稿