RubyからC++のクラスを使用する
RubyからC++のクラスを呼び出す例をまとめる。環境は以下の通り。
ANTLR(2.7.7)で生成されたC++によるパーサプログラムを、Rubyから呼び出すために調べたものをまとめてみた。ANTLRも3.0からはRubyも対象言語に含まれているので、わざわざC++のクラスを呼び出すこともなくなるだろう。
クラス定義
まず、C++のクラス定義から。
クラスExmapleのヘッダファイルと定義ファイルを用意する。
Exaple.hpp
// Example.hpp #ifndef __Example_hpp #define __Example_hpp class Example { public: Example(void); ~Example(void); char* toUpper(char* str); char* toLower(char* str); void print(char* str1, char* str2, int num=1); }; #endif
Example.cpp
// Exmaple.cpp #include <stdio.h> #include <iostream> #include <ctype.h> #include "Example.hpp" Example::Example(void) { } Example::~Example(void) { } char* Example::toUpper(char* str) { char* p = str; while(*p) { *p = toupper(*p); p++; } return str; } char* Example::toLower(char* str) { char* p = str; while(*p) { *p = tolower(*p); p++; } return str; } void Example::print(char* str1, char* str2, int num) { int i; for(i=0; i<num; i++) { std::cout << str1 << " " << str2 << " " << std::endl; } }
呼び出し側のRubyプログラム
次に、Exampleクラスを使用するRubyプログラムex.rbを示す。
#!/usr/bin/env ruby $:.unshift File.join(File.dirname(__FILE__), ".") require 'example' e = Example::Example.new str1 = "aaa bbb ccc" p e.toUpper(str1) p str1 p e.toLower(str1) p str1 e.print("Hello, ", "World!") e.print("Print", "Message", 3)
C++クラスのラッパーを作成する
SWIGでクラスExampleのラッパーを作成する。
インタフェースファイルの作成
Exampleクラスのラッパーを指定するため、インタフェースファイルexample.iを以下のように作成する。
%module example %{ #include "Example.hpp" %} %include Example.hpp
Maikefileを自動生成させる
自分で作ってもいいが、面倒なのでRubyで作ってもらう。
Makefile生成用のRubyプログラムextconf.rbを以下に示す。
extconf.rb
require 'mkmf' $libs += " -lstdc++ " create_makefile("example")
実行する。
$ ruby extconf.rb $
ビルド
makeを実行する。また、SELinuxが設定されている場合は、chconコマンドを実行する必要がある。
$ make ... $ chcon -t texrel_shlib_t example.so $
実行
以下に実行結果を示す。
$ ruby ex.ruby "AAA BBB CCC" "AAA BBB CCC" "aaa bbb ccc" "aaa bbb ccc" Hello, World! Print Message Print Message Print Message $
まとめ
一連の作業を以下のようにスクリプトにしておくと便利。
$ cat build.sh /bin/rm -fr *.so *.o *.cxx swig -c++ -ruby example.i ruby extconf.rb make chcon -t texrel_shlib_t example.so $