拡張ライブラリチュートリアルをやってみる#1

なんかlibyamlを移植することになったらしいので,ちょっとやってみる.

参考:Ruby拡張ライブラリ作成チュートリアル

「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 のオブジェクトを保存できる.

処理の流れ
  1. Rubyが test ライブラリを読み込む
require 'test'
  1. Init_test を実行する
  2. rb_define_module で Test モジュールを登録する.戻り値は VALUE 型構造体.
VALUE rb_define_module(const char *name);
  1. 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);
  1. warp_hello では hello が実行され,Qnil(Ruby の nil)が返される.
コンパイルするするために

Makefile を作成するために,extconf.rb を作成します.

  • extconf.rb
require 'mkmf'
create_makefile('test')

なんか依存関係を見てファイルを生成しているようだけど,とりあえずおまじないとして覚えておく.

コンパイルして実行する
  • make
% ruby extconf.rb
% make
% ruby -r'test' -e'Test.hello'
Hello, world!

特に値を引き渡さないのであれば,さっとできる感じ.