ページ

2011年7月1日金曜日

Rubyの拡張ライブラリをC++で書く場合のメモ


ライブラリとしてロードされる関数は、C リンケージ化しておく


require “libcore.so”

としてRubyプログラムからロードしたい場合は以下のように書く。
extern "C" {
void Init_libcore();
}
void
Init_libcore()
{
// ロード時に呼び出したい初期化処理
// ここではSoundというRubyクラス作成処理を呼び出している
SoundAdapter::init();
}

作成するRubyクラスのC++実装部は、class method化しておく (static付けとく)


SoundというRubyクラスを実装する例
class SoundAdapter
{
public:
static VALUE cSound;
static void init();
static VALUE ruby_new(VALUE self);
static VALUE ruby_loadSound(VALUE self, VALUE fileName);
}
void
SoundAdapter::init()
{
cSound = rb_define_class("Sound", rb_cObject);
rb_define_singleton_method (cSound, "new",RUBY_METHOD_FUNC(ruby_new), -1);
rb_define_method(cSound, "loadSound",RUBY_METHOD_FUNC(ruby_loadSound), 1);
}

rdocに認識してもらうためには



  • rb_define_method()等では、RUBY_METHOD_FUNC()を使用 (これによりrdocのパーサが定義クラスのメソッドとして認識してくれるため)

  • class method処理内容は自動で認識してくれないので、コメントで頑張る


/*
* Document-method: new
*
* call-seq:
*  new() -> SoundObject
*
* fileNameの音声ファイルをロードし、そのfileIdを返却するメソッド。
*
* ====Return
* 音声ファイルID
*/
VALUE
SoundAdapter::ruby_new(VALUE self)
{
Sound* sound = new Sound();
return Data_Wrap_Struct(cSound, NULL, NULL, sound);
}
/*
* Document-method: loadSound
*
* call-seq:
*  loadSound(fileName) -> fileId
*
* fileNameの音声ファイルをロードし、そのfileIdを返却するメソッド。
*
* ==== Args
* fineName: 音声ファイル
* ==== Return
* fileId: 音声ファイルID
*/
VALUE
SoundAdapter::ruby_loadSound(VALUE self, VALUE fileName)
{
Sound *sound;
Data_Get_Struct(self, Sound, sound);
int fileId = sound->loadSound(StringValuePtr(fileName));
return INT2NUM(fileId);
}

1 件のコメント: