[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 定数定義』で紹介さ
れている関数を使ってください.

In This Thread

Prev Next