[ruby-list:77] Ruby extension howto (sono 3)
From:
matz@... (Yukihiro Matsumoto)
Date:
1996-01-23 03:13:40 UTC
List:
ruby-list #77
まつもと ゆきひろ@トヨタケーラムです. ruby拡張モジュール作成講座の3回目です. -- 3.rubyとCとの情報共有 C言語とrubyの間で情報を共有する方法について解説します. 3.1 Cから参照できるrubyの定数 以下のrubyの定数はCのレベルから参照できる. TRUE FALSE 真偽値.FALSEはC言語でも偽とみなされる. Qnil C言語から見た「nil」. 3.2 Cとrubyで共有される大域変数 Cとrubyで大域変数を使って情報を共有できます.共有できる大域 変数にはいくつかの種類があります.そのなかでもっとも良く使わ れると思われるのはrb_define_variable()です. void rb_define_variable(char *name, VALUE *var) この関数はrubyとCとで共有する大域変数を定義します.変数名が `$'で始まらない時には自動的に追加されます.この変数の値を変 更すると自動的にrubyの対応する変数の値も変わります. またruby側からは更新できない変数もあります.このread onlyの 変数は以下の関数で定義します. void rb_define_readonly_variable(char *name, VALUE *var) これら変数の他にhookをつけた大域変数を定義できます.hook付き の大域変数は以下の関数を用いて定義します. void rb_define_hooked_variable(char *name, VALUE *var, VALUE (*getter)(), VALUE (*setter)()) この関数はCの関数によってhookのつけられた大域変数を定義しま す.変数が参照された時には関数getterが,変数に値がセットされ た時には関数setterが呼ばれる.hookを指定しない場合はgetterや setterに0を指定する. # getterもsetterも0ならばrb_define_variable()と同じになる. それから,Cの関数によって実現されるrubyの大域変数を定義する 関数があります. void rb_define_virtual_variable(char *name, VALUE (*getter)(), VALUE (*setter)()) この関数によって定義されたrubyの大域変数が参照された時には getterが,変数に値がセットされた時にはsetterが呼ばれます. 3.3 Cのデータをrubyオブジェクトにする Cの世界で定義されたデータ(構造体)をrubyのオブジェクトとして 取り扱いたい場合がありえます.このような場合には,Dataという rubyオブジェクトにCの構造体(へのポインタ)をくるむことでruby オブジェクトとして取り扱えるようになります. Dataオブジェクトを生成して構造体をrubyオブジェクトにカプセル 化するためには,以下の関数を使います. VALUE data_new(void *ptr, void (*mark)(), void (*free)()) ptrはカプセル化するCの構造体へのポインタです.markはこの構造 体がrubyのオブジェクトへの参照がある時に使う関数です.そのよ うな参照を含まない時には0を指定します. # そのような参照は勧められません. freeはこの構造体がもう不要になった時に呼ばれる関数です.この 関数がガーベージコレクタから呼ばれます. 通常はこのDataオブジェクトをユーザが定義したrubyクラスのイン スタンスのインスタンス変数として格納します.そのためのマクロ として以下のものが提供されています. Make_Data_Struct(obj, iv, type, mark, free, sval) ここでobjはインスタンス変数としてDataを代入するオブジェクト で,ivはインスタンス変数名を表すID,typeはカプセル化するCの データの型(構造体),mark, freeは上のdata_new()の解説の通りで す.そして,svalはtype型の変数です. このマクロを呼び出すとsvalに構造体がmalloc()されて代入され, かつその構造体をカプセル化したDataオブジェクトがインスタンス 変数としてobjにセットされます. Get_Data_Struct(objm iv, type, sval) これらのDataの使い方はちょっと分かりにくいので,後で説明する 例題を参照してください.