拡張ライブラリチュートリアルをやってみる#1
なんかlibyamlを移植することになったらしいので,ちょっとやってみる.
「Hello, world」を表示するために
処理内容を記述したファイル
まずライブラリ本体.処理内容を C 言語で記述したファイル.
- hello.c
#include <stdio.h> void hello() { printf("Hello, world!\n"); }
C と Ruby を繋ぐファイル
次に,ライブラリを呼出実行できるようにする,Ruby のモジュールを作成するための C 言語で記述したファイル.
- test1.c
#include "ruby.h" void hello(); VALUE wrap_hello(self) VALUE self; { hello(); return Qnil; } void Init_test() { VALUE module; module = rb_define_module("Test"); rb_define_module_function(module, "hello", wrap_hello, 0); }
ここで ruby.h には繋ぐための仕組みなどが記述されているらしいが,この段階ではまだ見てない.VALUE は構造体で,Ruby のオブジェクトを保存できる.
処理の流れ
- Rubyが test ライブラリを読み込む
require 'test'
- Init_test を実行する
- rb_define_module で Test モジュールを登録する.戻り値は VALUE 型構造体.
VALUE rb_define_module(const char *name);
- rb_define_module_function で module(つまり Test モジュール)に hello メソッドを登録する.wrap_hello は関数ポインタで,引数の数は 0 個.self という VALUE 型構造体が第一引数として渡されるらしい.
void rb_define_module_function(VALUE module, const char *name, VALUE (*func)(), int argc);
コンパイルするするために
Makefile を作成するために,extconf.rb を作成します.
- extconf.rb
require 'mkmf' create_makefile('test')
なんか依存関係を見てファイルを生成しているようだけど,とりあえずおまじないとして覚えておく.
コンパイルして実行する
- make
% ruby extconf.rb % make % ruby -r'test' -e'Test.hello' Hello, world!
特に値を引き渡さないのであれば,さっとできる感じ.