[ruby-list:76] Ruby extension howto (sono 2)
From:
matz@... (Yukihiro Matsumoto)
Date:
1996-01-22 09:24:04 UTC
List:
ruby-list #76
まつもと ゆきひろ@トヨタケーラムです. ruby拡張モジュール作成講座の2回目です. -- 2.rubyの機能を使う 原理的にrubyで書けることはCでも書けます.rubyそのものがCで記 述されているんですから,当然といえば当然なんですけど.ここで はrubyの拡張に使うことが多いだろうと予測される機能を中心に紹 介します. 2.1 rubyに機能を追加する rubyで提供されている関数を使えばrubyインタプリタに新しい機能 を追加することができます.rubyでは以下の機能を追加する関数が 提供されています. * クラス,モジュール * メソッド,特異メソッドなど * 定数 では順に紹介します. 2.1.1 クラス/モジュール定義 クラスやモジュールを定義するためには,以下の関数を使います. VALUE rb_define_class(char *name, VALUE super) VALUE rb_define_module(char *name) これらの関数は新しく定義されたクラスやモジュールを返します. メソッドや定数の定義にこれらの値が必要なので,ほとんどの場合 は戻り値を変数に格納しておく必要があるでしょう. 2.1.2 メソッド/特異メソッド定義 メソッドや特異メソッドを定義するには以下の関数を使います. void rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc) void rb_define_sigleton_method(VALUE object, char *name, VALUE (*func)(), int argc) 念のため説明すると「特異メソッド」とは,その特定のオブジェク トに対してだけ有効なメソッドです.rubyではよくSmalltalkにお けるクラスメソッドとして,クラスに対する特異メソッドが使われ ます. これらの関数の argcという引数はCの関数へ渡される引数の数(と 形式)を決めます.argcが正の時は関数に引き渡す引数の数を意味 します.16個以上の引数は使えません(が,要りませんよね,そん なに). argcが負の時は引数の数ではなく,形式を指定したことになります. argcが-1の時は引数を配列に入れて渡されます.argcが-2の時は引 数はrubyの配列として渡されます. メソッドを定義する関数はもう二つあります.ひとつはprivateメ ソッドを定義する関数で,引数はrb_define_method()と同じです. void rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc) privateメソッドとは関数形式でしか呼び出すことの出来ないメソッ ドです. もうひとつはモジュール関数を定義するものです.モジュール関数 とはモジュールの特異メソッドであり,同時にprivateメソッドで もあるものです.例をあげるとMathモジュールのsqrt()などがあげ られます.このメソッドは Math.sqrt(4) という形式でも include Math sqrt(4) という形式でも使えます.モジュール関数を定義する関数は以下の 通りです. void rb_define_private_method(VALUE module, char *name, VALUE (*func)(), int argc) 2.1.3 定数定義 拡張モジュールが必要な定数はあらかじめ定義しておいた方が良い でしょう.定数を定義する関数は二つあります. void rb_define_const(VALUE class, char *name, VALUE val) void rb_define_global_const(char *name, VALUE val) 前者は特定のクラス/モジュールに属する定数を定義するもの,後 者はグローバルな定数を定義するものです. 2.2 rubyの機能をCから呼び出す 既に『1.5 rubyのデータを操作する』で一部紹介したような関数を 使えば,rubyの機能を実現している関数を直接呼び出すことが出来 ます. # このような関数の一覧表はいまのところありません.ソースを見 # るしかないですね. それ以外にもrubyの機能を呼び出す方法はいくつかあります. 2.2.1 rubyのプログラムをevalする Cからrubyの機能を呼び出すもっとも簡単な方法として,文字列で 与えられたrubyのプログラムを評価する関数があります. VALUE rb_eval_string(char *str) この評価は現在の環境で行われます.つまり,現在のローカル変数 やselfなどを受け継ぎます. 2.2.2 IDまたはシンボル Cから文字列を経由せずにrubyのメソッドを呼び出すこともできま す.その前に,rubyインタプリタ内でメソッドや変数名を指定する 時に使われているIDについて説明しておきましょう. IDとは変数名,メソッド名を表す整数です.rubyの中では :識別子 でアクセスできます.Cからこの整数を得るためには関数 rb_intern(char *name) を使います. 2.2.3 Cからrubyのメソッドを呼び出す Cから文字列を経由せずにrubyのメソッドを呼び出すためには以下 の関数を使います. VALUE rb_funcall(VALUE recv, ID mid, int argc, ...) この関数はオブジェクトrecvのmidで指定されるメソッドを呼び出 します. 2.2.4 変数/定数を参照/更新する Cから関数を使って参照・更新できるのは,クラス定数,インスタ ンス変数です.大域変数は一部のものはCの大域変数としてアクセ スできます.ローカル変数を参照する方法は公開していません. オブジェクトのインスタンス変数を参照・更新する関数は以下の通 りです. rb_ivar_get(VALUE obj, ID id) rb_ivar_get(VALUE obj, ID id, VALUE val) idはrb_intern()で得られるものを使ってください. クラス定数を参照するには以下の関数を使ってください. rb_const_get(VALUE obj, ID id) クラス定数を新しく定義するためには『2.1.3 定数定義』で紹介さ れている関数を使ってください.