Bug #13229 » doc_extension_title.patch
| doc/extension.ja.rdoc | ||
|---|---|---|
| 
     # extension.ja.rdoc -  -*- RDoc -*- created at: Mon Aug  7 16:45:54 JST 1995 
   | 
||
| 
     = Creating Extension Libraries for Ruby 
   | 
||
| 
     Rubyの拡張ライブラリの作り方を説明します. 
   | 
||
| 
     = 基礎知識 
   | 
||
| 
     == 基礎知識 
   | 
||
| 
     Cの変数には型があり,データには型がありません.ですから,た 
   | 
||
| 
     とえばポインタをintの変数に代入すると,その値は整数として取 
   | 
||
| ... | ... | |
| 
     の両方が必要です.(1)を忘れると間違ったデータの変換が行われ 
   | 
||
| 
     て,最悪プログラムがcore dumpします. 
   | 
||
| 
     == データタイプ 
   | 
||
| 
     === データタイプ 
   | 
||
| 
     Rubyにはユーザが使う可能性のある以下のタイプがあります. 
   | 
||
| ... | ... | |
| 
     ほとんどのタイプはCの構造体で実装されています. 
   | 
||
| 
     == VALUEのデータタイプをチェックする 
   | 
||
| 
     === VALUEのデータタイプをチェックする 
   | 
||
| 
     ruby.hではTYPE()というマクロが定義されていて,VALUEのデータ 
   | 
||
| 
     タイプを知ることが出来ます.TYPE()マクロは上で紹介したT_XXXX 
   | 
||
| ... | ... | |
| 
       FIXNUM_P(obj) 
   | 
||
| 
       NIL_P(obj) 
   | 
||
| 
     == VALUEをCのデータに変換する 
   | 
||
| 
     === VALUEをCのデータに変換する 
   | 
||
| 
     データタイプがT_NIL,T_FALSE,T_TRUEである時,データはそれぞ 
   | 
||
| 
     れnil,false,trueです.このデータタイプのオブジェクトはひと 
   | 
||
| ... | ... | |
| 
     ないことです.直接変更した場合,オブジェクトの内容の整合性が 
   | 
||
| 
     とれなくなって,思わぬバグの原因になります. 
   | 
||
| 
     == CのデータをVALUEに変換する 
   | 
||
| 
     === CのデータをVALUEに変換する 
   | 
||
| 
     VALUEの実際の構造は 
   | 
||
| ... | ... | |
| 
     INT2NUM()は整数がFIXNUMの範囲に収まらない場合,Bignumに変換 
   | 
||
| 
     してくれます(が,少し遅い). 
   | 
||
| 
     == Rubyのデータを操作する 
   | 
||
| 
     === Rubyのデータを操作する 
   | 
||
| 
     先程も述べた通り,Rubyの構造体をアクセスする時に内容の更新を 
   | 
||
| 
     行うことは勧められません.で,Rubyのデータを操作する時には 
   | 
||
| ... | ... | |
| 
     ここではもっとも使われるであろう文字列と配列の生成/操作を行 
   | 
||
| 
     う関数をあげます(全部ではないです). 
   | 
||
| 
     === 文字列に対する関数 
   | 
||
| 
     ==== 文字列に対する関数 
   | 
||
| 
     rb_str_new(const char *ptr, long len) :: 
   | 
||
| ... | ... | |
| 
       lenバイトまでの内容は保存される.lenはstrの容量を越えてい 
   | 
||
| 
       てはならない. 
   | 
||
| 
     === 配列に対する関数 
   | 
||
| 
     ==== 配列に対する関数 
   | 
||
| 
     rb_ary_new() :: 
   | 
||
| ... | ... | |
| 
       配列aryにptrからlen個のオブジェクトを追加する. 
   | 
||
| 
     = Rubyの機能を使う 
   | 
||
| 
     == Rubyの機能を使う 
   | 
||
| 
     原理的にRubyで書けることはCでも書けます.RubyそのものがCで記 
   | 
||
| 
     述されているんですから,当然といえば当然なんですけど.ここで 
   | 
||
| 
     はRubyの拡張に使うことが多いだろうと予測される機能を中心に紹 
   | 
||
| 
     介します. 
   | 
||
| 
     == Rubyに機能を追加する 
   | 
||
| 
     === Rubyに機能を追加する 
   | 
||
| 
     Rubyで提供されている関数を使えばRubyインタプリタに新しい機能 
   | 
||
| 
     を追加することができます.Rubyでは以下の機能を追加する関数が 
   | 
||
| ... | ... | |
| 
     では順に紹介します. 
   | 
||
| 
     === クラス/モジュール定義 
   | 
||
| 
     ==== クラス/モジュール定義 
   | 
||
| 
     クラスやモジュールを定義するためには,以下の関数を使います. 
   | 
||
| ... | ... | |
| 
       VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) 
   | 
||
| 
       VALUE rb_define_module_under(VALUE outer, const char *name) 
   | 
||
| 
     === メソッド/特異メソッド定義 
   | 
||
| 
     ==== メソッド/特異メソッド定義 
   | 
||
| 
     メソッドや特異メソッドを定義するには以下の関数を使います. 
   | 
||
| ... | ... | |
| 
       VALUE rb_current_receiver(void) 
   | 
||
| 
     === 定数定義 
   | 
||
| 
     ==== 定数定義 
   | 
||
| 
     拡張ライブラリが必要な定数はあらかじめ定義しておいた方が良い 
   | 
||
| 
     でしょう.定数を定義する関数は二つあります. 
   | 
||
| ... | ... | |
| 
     前者は特定のクラス/モジュールに属する定数を定義するもの,後 
   | 
||
| 
     者はグローバルな定数を定義するものです. 
   | 
||
| 
     == Rubyの機能をCから呼び出す 
   | 
||
| 
     === Rubyの機能をCから呼び出す 
   | 
||
| 
     既に『1.5 Rubyのデータを操作する』で一部紹介したような関数を 
   | 
||
| 
     使えば,Rubyの機能を実現している関数を直接呼び出すことが出来 
   | 
||
| ... | ... | |
| 
     それ以外にもRubyの機能を呼び出す方法はいくつかあります. 
   | 
||
| 
     === Rubyのプログラムをevalする 
   | 
||
| 
     ==== Rubyのプログラムをevalする 
   | 
||
| 
     CからRubyの機能を呼び出すもっとも簡単な方法として,文字列で 
   | 
||
| 
     与えられたRubyのプログラムを評価する以下の関数があります. 
   | 
||
| ... | ... | |
| 
     この関数はエラーが発生するとnilを返します.そして,成功時には 
   | 
||
| 
     *stateはゼロに,さもなくば非ゼロになります. 
   | 
||
| 
     === IDまたはシンボル 
   | 
||
| 
     ==== IDまたはシンボル 
   | 
||
| 
     Cから文字列を経由せずにRubyのメソッドを呼び出すこともできま 
   | 
||
| 
     す.その前に,Rubyインタプリタ内でメソッドや変数名を指定する 
   | 
||
| ... | ... | |
| 
     これらの関数は,IDの代わりにシンボルを返すことを除けば上記の 
   | 
||
| 
     関数と同じです. 
   | 
||
| 
     === CからRubyのメソッドを呼び出す 
   | 
||
| 
     ==== CからRubyのメソッドを呼び出す 
   | 
||
| 
     Cから文字列を経由せずにRubyのメソッドを呼び出すためには以下 
   | 
||
| 
     の関数を使います. 
   | 
||
| ... | ... | |
| 
     applyには引数としてRubyの配列を与えます. 
   | 
||
| 
     === 変数/定数を参照/更新する 
   | 
||
| 
     ==== 変数/定数を参照/更新する 
   | 
||
| 
     Cから関数を使って参照・更新できるのは,定数,インスタンス変 
   | 
||
| 
     数です.大域変数は一部のものはCの大域変数としてアクセスでき 
   | 
||
| ... | ... | |
| 
     定数を新しく定義するためには『2.1.3 定数定義』で紹介さ 
   | 
||
| 
     れている関数を使ってください. 
   | 
||
| 
     = RubyとCとの情報共有 
   | 
||
| 
     == RubyとCとの情報共有 
   | 
||
| 
     C言語とRubyの間で情報を共有する方法について解説します. 
   | 
||
| 
     == Cから参照できるRubyの定数 
   | 
||
| 
     === Cから参照できるRubyの定数 
   | 
||
| 
     以下のRubyの定数はCのレベルから参照できます. 
   | 
||
| ... | ... | |
| 
       C言語から見た「nil」. 
   | 
||
| 
     == CとRubyで共有される大域変数 
   | 
||
| 
     === CとRubyで共有される大域変数 
   | 
||
| 
     CとRubyで大域変数を使って情報を共有できます.共有できる大域 
   | 
||
| 
     変数にはいくつかの種類があります.そのなかでもっとも良く使わ 
   | 
||
| ... | ... | |
| 
       (*getter)(ID id); 
   | 
||
| 
       (*setter)(VALUE val, ID id); 
   | 
||
| 
     == CのデータをRubyオブジェクトにする 
   | 
||
| 
     === CのデータをRubyオブジェクトにする 
   | 
||
| 
     Cの世界で定義されたデータ(構造体)をRubyのオブジェクトとして 
   | 
||
| 
     取り扱いたい場合がありえます.このような場合はTypedData_XXX 
   | 
||
| ... | ... | |
| 
     があります. 
   | 
||
| 
     ++ 
   | 
||
| 
     === 構造体からオブジェクトへ 
   | 
||
| 
     ==== 構造体からオブジェクトへ 
   | 
||
| 
     構造体へのポインタsvalをRubyオブジェクトに変換するには次のマ 
   | 
||
| 
     クロを使います。 
   | 
||
| ... | ... | |
| 
     は割り当てるC構造体の型です.割り当てられた構造体は変数sval 
   | 
||
| 
     に代入されます.この変数の型は (type*) である必要があります. 
   | 
||
| 
     === オブジェクトから構造体へ 
   | 
||
| 
     ==== オブジェクトから構造体へ 
   | 
||
| 
     TypedData_Wrap_StructやTypedData_Make_Structで生成したオブジェ 
   | 
||
| 
     クトから構造体へのポインタを復元するには以下のマクロを用いま 
   | 
||
| ... | ... | |
| 
     これらのマクロの使い方はちょっと分かりにくいので,後で説明す 
   | 
||
| 
     る例題を参照してください. 
   | 
||
| 
     == ディレクトリを作る 
   | 
||
| 
     == Example - Creating the dbm Extension 
   | 
||
| 
     === ディレクトリを作る 
   | 
||
| 
       % mkdir ext/dbm 
   | 
||
| ... | ... | |
| 
     ライブラリ用のディレクトリを作る必要があります.名前は適当に 
   | 
||
| 
     選んで構いません. 
   | 
||
| 
     == 設計する 
   | 
||
| 
     === 設計する 
   | 
||
| 
     まあ,当然なんですけど,どういう機能を実現するかどうかまず設 
   | 
||
| 
     計する必要があります.どんなクラスをつくるか,そのクラスには 
   | 
||
| 
     どんなメソッドがあるか,クラスが提供する定数などについて設計 
   | 
||
| 
     します. 
   | 
||
| 
     == Cコードを書く 
   | 
||
| 
     === Cコードを書く 
   | 
||
| 
     拡張ライブラリ本体となるC言語のソースを書きます.C言語のソー 
   | 
||
| 
     スがひとつの時には「ライブラリ名.c」を選ぶと良いでしょう.C 
   | 
||
| ... | ... | |
| 
       void rb_global_variable(VALUE *var) 
   | 
||
| 
     == extconf.rbを用意する 
   | 
||
| 
     === extconf.rbを用意する 
   | 
||
| 
     Makefileを作る場合の雛型になるextconf.rbというファイルを作り 
   | 
||
| 
     ます.extconf.rbはライブラリのコンパイルに必要な条件のチェッ 
   | 
||
| ... | ... | |
| 
     パイルしない時にはcreate_makefileを呼ばなければMakefileは生 
   | 
||
| 
     成されず,コンパイルも行われません. 
   | 
||
| 
     == dependを用意する 
   | 
||
| 
     === dependを用意する 
   | 
||
| 
     もし,ディレクトリにdependというファイルが存在すれば, 
   | 
||
| 
     Makefileが依存関係をチェックしてくれます. 
   | 
||
| ... | ... | |
| 
     などで作ることが出来ます.あって損は無いでしょう. 
   | 
||
| 
     == Makefileを生成する 
   | 
||
| 
     === Makefileを生成する 
   | 
||
| 
     Makefileを実際に生成するためには 
   | 
||
| ... | ... | |
| 
     ディレクトリをext以下に用意した場合にはRuby全体のmakeの時に 
   | 
||
| 
     自動的にMakefileが生成されますので,このステップは不要です. 
   | 
||
| 
     == makeする 
   | 
||
| 
     === makeする 
   | 
||
| 
     動的リンクライブラリを生成する場合にはその場でmakeしてくださ 
   | 
||
| 
     い.必要であれば make install でインストールされます. 
   | 
||
| ... | ... | |
| 
     を作り,そこに 拡張子 .rb のファイルを置いておけば同時にイン 
   | 
||
| 
     ストールされます. 
   | 
||
| 
     == デバッグ 
   | 
||
| 
     === デバッグ 
   | 
||
| 
     まあ,デバッグしないと動かないでしょうね.ext/Setupにディレ 
   | 
||
| 
     クトリ名を書くと静的にリンクするのでデバッガが使えるようにな 
   | 
||
| 
     ります.その分コンパイルが遅くなりますけど. 
   | 
||
| 
     == できあがり 
   | 
||
| 
     === できあがり 
   | 
||
| 
     後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお 
   | 
||
| 
     使いください.Rubyの作者は拡張ライブラリに関して一切の権利を 
   | 
||
| 
     主張しません. 
   | 
||
| 
     = Appendix A. Rubyのソースコードの分類 
   | 
||
| 
     == Appendix A. Rubyのソースコードの分類 
   | 
||
| 
     Rubyのソースはいくつかに分類することが出来ます.このうちクラ 
   | 
||
| 
     スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ 
   | 
||
| 
     ています.これらのソースは今までの説明でほとんど理解できると 
   | 
||
| 
     思います. 
   | 
||
| 
     == Ruby言語のコア 
   | 
||
| 
     === Ruby言語のコア 
   | 
||
| 
     class.c    :: クラスとモジュール 
   | 
||
| 
     error.c    :: 例外クラスと例外機構 
   | 
||
| ... | ... | |
| 
     object.c   :: オブジェクト 
   | 
||
| 
     variable.c :: 変数と定数 
   | 
||
| 
     == Rubyの構文解析器 
   | 
||
| 
     === Rubyの構文解析器 
   | 
||
| 
     parse.y       :: 字句解析器と構文定義 
   | 
||
| 
     parse.c       :: 自動生成 
   | 
||
| 
     defs/keywords :: 予約語 
   | 
||
| 
     lex.c         :: 自動生成 
   | 
||
| 
     == Rubyの評価器 (通称YARV) 
   | 
||
| 
     === Rubyの評価器 (通称YARV) 
   | 
||
| 
       compile.c 
   | 
||
| 
       eval.c 
   | 
||
| ... | ... | |
| 
         -> opt*.inc            : 自動生成 
   | 
||
| 
         -> vm.inc              : 自動生成 
   | 
||
| 
     == 正規表現エンジン (鬼車) 
   | 
||
| 
     === 正規表現エンジン (鬼車) 
   | 
||
| 
       regex.c 
   | 
||
| 
       regcomp.c 
   | 
||
| ... | ... | |
| 
       regparse.c 
   | 
||
| 
       regsyntax.c 
   | 
||
| 
     == ユーティリティ関数 
   | 
||
| 
     === ユーティリティ関数 
   | 
||
| 
     debug.c    :: Cデバッガ用のデバッグシンボル 
   | 
||
| 
     dln.c      :: 動的ローディング 
   | 
||
| ... | ... | |
| 
     strftime.c :: 時刻整形 
   | 
||
| 
     util.c     :: その他のユーティリティ 
   | 
||
| 
     == Rubyコマンドの実装 
   | 
||
| 
     === Rubyコマンドの実装 
   | 
||
| 
       dmyext.c 
   | 
||
| 
       dmydln.c 
   | 
||
| ... | ... | |
| 
       gem_prelude.rb 
   | 
||
| 
       prelude.rb 
   | 
||
| 
     == クラスライブラリ 
   | 
||
| 
     === クラスライブラリ 
   | 
||
| 
     array.c      :: Array 
   | 
||
| 
     bignum.c     :: Bignum 
   | 
||
| ... | ... | |
| 
     defs/known_errors.def :: 例外クラス Errno::* 
   | 
||
| 
     -> known_errors.inc   :: 自動生成 
   | 
||
| 
     == 多言語化 
   | 
||
| 
     === 多言語化 
   | 
||
| 
     encoding.c  :: Encoding 
   | 
||
| 
     transcode.c :: Encoding::Converter 
   | 
||
| 
     enc/*.c     :: エンコーディングクラス群 
   | 
||
| 
     enc/trans/* :: コードポイント対応表 
   | 
||
| 
     == gorubyコマンドの実装 
   | 
||
| 
     === gorubyコマンドの実装 
   | 
||
| 
       goruby.c 
   | 
||
| 
       golf_prelude.rb      : goruby固有のライブラリ 
   | 
||
| 
         -> golf_prelude.c  : 自動生成 
   | 
||
| 
     = Appendix B. 拡張用関数リファレンス 
   | 
||
| 
     == Appendix B. 拡張用関数リファレンス 
   | 
||
| 
     C言語からRubyの機能を利用するAPIは以下の通りである. 
   | 
||
| 
     == 型 
   | 
||
| 
     === 型 
   | 
||
| 
     VALUE :: 
   | 
||
| ... | ... | |
| 
       体である.VALUE型をこれらにキャストするためにRで始まる構造体 
   | 
||
| 
       名を全て大文字にした名前のマクロが用意されている. 
   | 
||
| 
     == 変数・定数 
   | 
||
| 
     === 変数・定数 
   | 
||
| 
     Qnil :: 
   | 
||
| ... | ... | |
| 
       定数: falseオブジェクト 
   | 
||
| 
     == Cデータのカプセル化 
   | 
||
| 
     === Cデータのカプセル化 
   | 
||
| 
     Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval) :: 
   | 
||
| ... | ... | |
| 
       dataからtype型のポインタを取り出し変数svalに代入するマクロ. 
   | 
||
| 
     == 型チェック 
   | 
||
| 
     === 型チェック 
   | 
||
| 
       RB_TYPE_P(value, type) 
   | 
||
| 
       TYPE(value) 
   | 
||
| ... | ... | |
| 
       void Check_Type(VALUE value, int type) 
   | 
||
| 
       SafeStringValue(value) 
   | 
||
| 
     == 型変換 
   | 
||
| 
     === 型変換 
   | 
||
| 
       FIX2INT(value), INT2FIX(i) 
   | 
||
| 
       FIX2LONG(value), LONG2FIX(l) 
   | 
||
| ... | ... | |
| 
       StringValueCStr(value) 
   | 
||
| 
       rb_str_new2(s) 
   | 
||
| 
     == クラス/モジュール定義 
   | 
||
| 
     === クラス/モジュール定義 
   | 
||
| 
     VALUE rb_define_class(const char *name, VALUE super) :: 
   | 
||
| ... | ... | |
| 
       オブジェクトをモジュール(で定義されているメソッド)で拡張する. 
   | 
||
| 
     == 大域変数定義 
   | 
||
| 
     === 大域変数定義 
   | 
||
| 
     void rb_define_variable(const char *name, VALUE *var) :: 
   | 
||
| ... | ... | |
| 
       GCのため,Rubyプログラムからはアクセスされないが, Rubyオブ 
   | 
||
| 
       ジェクトを含む大域変数をマークする. 
   | 
||
| 
     == 定数 
   | 
||
| 
     === 定数 
   | 
||
| 
     void rb_define_const(VALUE klass, const char *name, VALUE val) :: 
   | 
||
| ... | ... | |
| 
       と同じ意味. 
   | 
||
| 
     == メソッド定義 
   | 
||
| 
     === メソッド定義 
   | 
||
| 
     rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) :: 
   | 
||
| ... | ... | |
| 
       先には,元のHashがSymbol以外のキーを含んでいた場合はそれらが 
   | 
||
| 
       コピーされた別の新しいHash,そうでなければ0が保存されます. 
   | 
||
| 
     == Rubyメソッド呼び出し 
   | 
||
| 
     === Rubyメソッド呼び出し 
   | 
||
| 
     VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) :: 
   | 
||
| ... | ... | |
| 
       objがidで示されるメソッドを持つかどうかを返す. 
   | 
||
| 
     == インスタンス変数 
   | 
||
| 
     === インスタンス変数 
   | 
||
| 
     VALUE rb_iv_get(VALUE obj, const char *name) :: 
   | 
||
| ... | ... | |
| 
       objのインスタンス変数をvalにセットする. 
   | 
||
| 
     == 制御構造 
   | 
||
| 
     === 制御構造 
   | 
||
| 
     VALUE rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2) :: 
   | 
||
| ... | ... | |
| 
       現在の最も内側のブロックをvalueで終了する.ブロックは引数で 
   | 
||
| 
       与えられたvalueを返す.この関数は直接の呼び出し元に戻らない. 
   | 
||
| 
     == 例外・エラー 
   | 
||
| 
     === 例外・エラー 
   | 
||
| 
     void rb_warning(const char *fmt, ...) :: 
   | 
||
| ... | ... | |
| 
     きはObject#inspect)を使ったVALUEの出力に利用できる.これは 
   | 
||
| 
     "%i"と衝突するため,整数には"%d"を使用すること. 
   | 
||
| 
     == Rubyの初期化・実行 
   | 
||
| 
     === Rubyの初期化・実行 
   | 
||
| 
     Rubyをアプリケーションに埋め込む場合には以下のインタフェース 
   | 
||
| 
     を使う.通常の拡張ライブラリには必要ない. 
   | 
||
| ... | ... | |
| 
       Rubyのスクリプト名($0)を設定する. 
   | 
||
| 
     == インタプリタのイベントのフック 
   | 
||
| 
     === インタプリタのイベントのフック 
   | 
||
| 
     void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) :: 
   | 
||
| ... | ... | |
| 
       指定されたフック関数を削除します. 
   | 
||
| 
     == メモリ使用量 
   | 
||
| 
     === メモリ使用量 
   | 
||
| 
     void rb_gc_adjust_memory_usage(ssize_t diff) :: 
   | 
||
| ... | ... | |
| 
       す.メモリブロックが解放されたり,メモリブロックがより小さいサイズで再 
   | 
||
| 
       確保されたりした場合などです.この関数はGCを引き起こすかもしれません. 
   | 
||
| 
     == 互換性のためのマクロ 
   | 
||
| 
     === 互換性のためのマクロ 
   | 
||
| 
     APIの互換性をチェックするために以下のマクロがデフォルトで定義されています. 
   | 
||
| ... | ... | |
| 
       rb_add_event_hook() がフック関数に渡す data を第3引数として 
   | 
||
| 
       受け取ることを意味する. 
   | 
||
| 
     = Appendix C. extconf.rbで使える関数たち 
   | 
||
| 
     == Appendix C. extconf.rbで使える関数たち 
   | 
||
| 
     extconf.rbの中では利用可能なコンパイル条件チェックの関数は以 
   | 
||
| 
     下の通りである. 
   | 
||
| ... | ... | |
| 
       optionが指定された場合は,上記の配列の代わりにそのオプションを 
   | 
||
| 
       指定して得られた出力をstripしたものを返す. 
   | 
||
| 
     = Appendix D. 世代別GC 
   | 
||
| 
     == Appendix D. 世代別GC 
   | 
||
| 
     Ruby 2.1から世代別GCに対応しました.我々はこれをRGenGCと呼んでいます. 
   | 
||
| 
     RGenGCは,過去の拡張ライブラリに(ほぼ)互換性を保つように開発されている 
   | 
||
| doc/extension.rdoc | ||
|---|---|---|
| 
     # extension.rdoc -  -*- RDoc -*- created at: Mon Aug  7 16:45:54 JST 1995 
   | 
||
| 
     = Creating Extension Libraries for Ruby 
   | 
||
| 
     This document explains how to make extension libraries for Ruby. 
   | 
||
| 
     = Basic Knowledge 
   | 
||
| 
     == Basic Knowledge 
   | 
||
| 
     In C, variables have types and data do not have types.  In contrast, 
   | 
||
| 
     Ruby variables do not have a static type, and data themselves have 
   | 
||
| ... | ... | |
| 
     Converting to the wrong data type may cause serious problems. 
   | 
||
| 
     == Data Types 
   | 
||
| 
     === Data Types 
   | 
||
| 
     The Ruby interpreter has the following data types: 
   | 
||
| ... | ... | |
| 
     Most of the types are represented by C structures. 
   | 
||
| 
     == Check Data Type of the VALUE 
   | 
||
| 
     === Check Data Type of the VALUE 
   | 
||
| 
     The macro TYPE() defined in ruby.h shows the data type of the VALUE. 
   | 
||
| 
     TYPE() returns the constant number T_XXXX described above.  To handle 
   | 
||
| ... | ... | |
| 
       FIXNUM_P(obj) 
   | 
||
| 
       NIL_P(obj) 
   | 
||
| 
     == Convert VALUE into C Data 
   | 
||
| 
     === Convert VALUE into C Data 
   | 
||
| 
     The data for type T_NIL, T_FALSE, T_TRUE are nil, false, true 
   | 
||
| 
     respectively.  They are singletons for the data type. 
   | 
||
| ... | ... | |
| 
     are responsible for the result.  This ends up being the cause of 
   | 
||
| 
     interesting bugs. 
   | 
||
| 
     == Convert C Data into VALUE 
   | 
||
| 
     === Convert C Data into VALUE 
   | 
||
| 
     To convert C data to Ruby values: 
   | 
||
| ... | ... | |
| 
     INT2NUM() converts an integer into a Bignum if it is out of the FIXNUM 
   | 
||
| 
     range, but is a bit slower. 
   | 
||
| 
     == Manipulating Ruby Data 
   | 
||
| 
     === Manipulating Ruby Data 
   | 
||
| 
     As I already mentioned, it is not recommended to modify an object's 
   | 
||
| 
     internal structure.  To manipulate objects, use the functions supplied 
   | 
||
| 
     by the Ruby interpreter. Some (not all) of the useful functions are 
   | 
||
| 
     listed below: 
   | 
||
| 
     === String Functions 
   | 
||
| 
     ==== String Functions 
   | 
||
| 
     rb_str_new(const char *ptr, long len) :: 
   | 
||
| ... | ... | |
| 
       up to len bytes, regardless RSTRING_LEN(str).  len must not exceed 
   | 
||
| 
       the capacity of str. 
   | 
||
| 
     === Array Functions 
   | 
||
| 
     ==== Array Functions 
   | 
||
| 
     rb_ary_new() :: 
   | 
||
| ... | ... | |
| 
       Appends len elements of objects from ptr to the array. 
   | 
||
| 
     = Extending Ruby with C 
   | 
||
| 
     == Extending Ruby with C 
   | 
||
| 
     == Adding New Features to Ruby 
   | 
||
| 
     === Adding New Features to Ruby 
   | 
||
| 
     You can add new features (classes, methods, etc.) to the Ruby 
   | 
||
| 
     interpreter.  Ruby provides APIs for defining the following things: 
   | 
||
| ... | ... | |
| 
     - Methods, Singleton Methods 
   | 
||
| 
     - Constants 
   | 
||
| 
     === Class and Module Definition 
   | 
||
| 
     ==== Class and Module Definition 
   | 
||
| 
     To define a class or module, use the functions below: 
   | 
||
| ... | ... | |
| 
       VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) 
   | 
||
| 
       VALUE rb_define_module_under(VALUE outer, const char *name) 
   | 
||
| 
     === Method and Singleton Method Definition 
   | 
||
| 
     ==== Method and Singleton Method Definition 
   | 
||
| 
     To define methods or singleton methods, use these functions: 
   | 
||
| ... | ... | |
| 
       VALUE rb_current_receiver(void) 
   | 
||
| 
     === Constant Definition 
   | 
||
| 
     ==== Constant Definition 
   | 
||
| 
     We have 2 functions to define constants: 
   | 
||
| ... | ... | |
| 
     The former is to define a constant under specified class/module.  The 
   | 
||
| 
     latter is to define a global constant. 
   | 
||
| 
     == Use Ruby Features from C 
   | 
||
| 
     === Use Ruby Features from C 
   | 
||
| 
     There are several ways to invoke Ruby's features from C code. 
   | 
||
| 
     === Evaluate Ruby Programs in a String 
   | 
||
| 
     ==== Evaluate Ruby Programs in a String 
   | 
||
| 
     The easiest way to use Ruby's functionality from a C program is to 
   | 
||
| 
     evaluate the string as Ruby program.  This function will do the job: 
   | 
||
| ... | ... | |
| 
     It returns nil when an error occurred. Moreover, *state is zero if str was 
   | 
||
| 
     successfully evaluated, or nonzero otherwise. 
   | 
||
| 
     === ID or Symbol 
   | 
||
| 
     ==== ID or Symbol 
   | 
||
| 
     You can invoke methods directly, without parsing the string.  First I 
   | 
||
| 
     need to explain about ID.  ID is the integer number to represent 
   | 
||
| ... | ... | |
| 
       ID SYM2ID(VALUE symbol) 
   | 
||
| 
     === Invoke Ruby Method from C 
   | 
||
| 
     ==== Invoke Ruby Method from C 
   | 
||
| 
     To invoke methods directly, you can use the function below 
   | 
||
| ... | ... | |
| 
     This function invokes a method on the recv, with the method name 
   | 
||
| 
     specified by the symbol mid. 
   | 
||
| 
     === Accessing the Variables and Constants 
   | 
||
| 
     ==== Accessing the Variables and Constants 
   | 
||
| 
     You can access class variables and instance variables using access 
   | 
||
| 
     functions.  Also, global variables can be shared between both 
   | 
||
| ... | ... | |
| 
     See also Constant Definition above. 
   | 
||
| 
     = Information Sharing Between Ruby and C 
   | 
||
| 
     == Information Sharing Between Ruby and C 
   | 
||
| 
     === Ruby Constants That Can Be Accessed From C 
   | 
||
| ... | ... | |
| 
       Ruby nil in C scope. 
   | 
||
| 
     == Global Variables Shared Between C and Ruby 
   | 
||
| 
     === Global Variables Shared Between C and Ruby 
   | 
||
| 
     Information can be shared between the two environments using shared global 
   | 
||
| 
     variables.  To define them, you can use functions listed below: 
   | 
||
| ... | ... | |
| 
       VALUE (*getter)(ID id); 
   | 
||
| 
       void (*setter)(VALUE val, ID id); 
   | 
||
| 
     == Encapsulate C Data into a Ruby Object 
   | 
||
| 
     === Encapsulate C Data into a Ruby Object 
   | 
||
| 
     Sometimes you need to expose your struct in the C world as a Ruby 
   | 
||
| 
     object. 
   | 
||
| ... | ... | |
| 
     work. 
   | 
||
| 
     ++ 
   | 
||
| 
     === C struct to Ruby object 
   | 
||
| 
     ==== C struct to Ruby object 
   | 
||
| 
     You can convert sval, a pointer to your struct, into a Ruby object 
   | 
||
| 
     with the next macro. 
   | 
||
| ... | ... | |
| 
     TypedData_Wrap_Struct().  A pointer to the allocated structure will 
   | 
||
| 
     be assigned to sval, which should be a pointer of the type specified. 
   | 
||
| 
     === Ruby object to C struct 
   | 
||
| 
     ==== Ruby object to C struct 
   | 
||
| 
     To retrieve the C pointer from the Data object, use the macro 
   | 
||
| 
     Data_Get_Struct(). 
   | 
||
| ... | ... | |
| 
     See the example below for details. 
   | 
||
| 
     = Example - Creating the dbm Extension 
   | 
||
| 
     == Example - Creating the dbm Extension 
   | 
||
| 
     OK, here's the example of making an extension library.  This is the 
   | 
||
| 
     extension to access DBMs.  The full source is included in the ext/ 
   | 
||
| 
     directory in the Ruby's source tree. 
   | 
||
| 
     == Make the Directory 
   | 
||
| 
     === Make the Directory 
   | 
||
| 
       % mkdir ext/dbm 
   | 
||
| 
     Make a directory for the extension library under ext directory. 
   | 
||
| 
     == Design the Library 
   | 
||
| 
     === Design the Library 
   | 
||
| 
     You need to design the library features, before making it. 
   | 
||
| 
     == Write the C Code 
   | 
||
| 
     === Write the C Code 
   | 
||
| 
     You need to write C code for your extension library.  If your library 
   | 
||
| 
     has only one source file, choosing ``LIBRARY.c'' as a file name is 
   | 
||
| ... | ... | |
| 
       void rb_global_variable(VALUE *var) 
   | 
||
| 
     == Prepare extconf.rb 
   | 
||
| 
     === Prepare extconf.rb 
   | 
||
| 
     If the file named extconf.rb exists, it will be executed to generate 
   | 
||
| 
     Makefile. 
   | 
||
| ... | ... | |
| 
     ``create_makefile''.  The Makefile will not be generated, compilation will 
   | 
||
| 
     not be done. 
   | 
||
| 
     == Prepare Depend (Optional) 
   | 
||
| 
     === Prepare Depend (Optional) 
   | 
||
| 
     If the file named depend exists, Makefile will include that file to 
   | 
||
| 
     check dependencies.  You can make this file by invoking 
   | 
||
| ... | ... | |
| 
     It's harmless.  Prepare it. 
   | 
||
| 
     == Generate Makefile 
   | 
||
| 
     === Generate Makefile 
   | 
||
| 
     Try generating the Makefile by: 
   | 
||
| ... | ... | |
| 
     directory of the ruby source tree.  In that case, compilation of the 
   | 
||
| 
     interpreter will do this step for you. 
   | 
||
| 
     == Run make 
   | 
||
| 
     === Run make 
   | 
||
| 
     Type 
   | 
||
| ... | ... | |
| 
     to compile your extension.  You don't need this step either if you have 
   | 
||
| 
     put the extension library under the ext directory of the ruby source tree. 
   | 
||
| 
     == Debug 
   | 
||
| 
     === Debug 
   | 
||
| 
     You may need to rb_debug the extension.  Extensions can be linked 
   | 
||
| 
     statically by adding the directory name in the ext/Setup file so that 
   | 
||
| 
     you can inspect the extension with the debugger. 
   | 
||
| 
     == Done! Now You Have the Extension Library 
   | 
||
| 
     === Done! Now You Have the Extension Library 
   | 
||
| 
     You can do anything you want with your library.  The author of Ruby 
   | 
||
| 
     will not claim any restrictions on your code depending on the Ruby API. 
   | 
||
| 
     Feel free to use, modify, distribute or sell your program. 
   | 
||
| 
     = Appendix A. Ruby Source Files Overview 
   | 
||
| 
     == Appendix A. Ruby Source Files Overview 
   | 
||
| 
     == Ruby Language Core 
   | 
||
| 
     === Ruby Language Core 
   | 
||
| 
     class.c    :: classes and modules 
   | 
||
| 
     error.c    :: exception classes and exception mechanism 
   | 
||
| ... | ... | |
| 
     object.c   :: objects 
   | 
||
| 
     variable.c :: variables and constants 
   | 
||
| 
     == Ruby Syntax Parser 
   | 
||
| 
     === Ruby Syntax Parser 
   | 
||
| 
     parse.y       :: grammar definition 
   | 
||
| 
     parse.c       :: automatically generated from parse.y 
   | 
||
| 
     defs/keywords :: reserved keywords 
   | 
||
| 
     lex.c         :: automatically generated from keywords 
   | 
||
| 
     == Ruby Evaluator (a.k.a. YARV) 
   | 
||
| 
     === Ruby Evaluator (a.k.a. YARV) 
   | 
||
| 
       compile.c 
   | 
||
| 
       eval.c 
   | 
||
| ... | ... | |
| 
         -> opt*.inc            : automatically generated 
   | 
||
| 
         -> vm.inc              : automatically generated 
   | 
||
| 
     == Regular Expression Engine (Oniguruma) 
   | 
||
| 
     === Regular Expression Engine (Oniguruma) 
   | 
||
| 
       regex.c 
   | 
||
| 
       regcomp.c 
   | 
||
| ... | ... | |
| 
       regparse.c 
   | 
||
| 
       regsyntax.c 
   | 
||
| 
     == Utility Functions 
   | 
||
| 
     === Utility Functions 
   | 
||
| 
     debug.c    :: debug symbols for C debugger 
   | 
||
| 
     dln.c      :: dynamic loading 
   | 
||
| ... | ... | |
| 
     strftime.c :: formatting times 
   | 
||
| 
     util.c     :: misc utilities 
   | 
||
| 
     == Ruby Interpreter Implementation 
   | 
||
| 
     === Ruby Interpreter Implementation 
   | 
||
| 
       dmyext.c 
   | 
||
| 
       dmydln.c 
   | 
||
| ... | ... | |
| 
       gem_prelude.rb 
   | 
||
| 
       prelude.rb 
   | 
||
| 
     == Class Library 
   | 
||
| 
     === Class Library 
   | 
||
| 
     array.c      :: Array 
   | 
||
| 
     bignum.c     :: Bignum 
   | 
||
| ... | ... | |
| 
     defs/known_errors.def :: Errno::* exception classes 
   | 
||
| 
     -> known_errors.inc   :: automatically generated 
   | 
||
| 
     == Multilingualization 
   | 
||
| 
     === Multilingualization 
   | 
||
| 
     encoding.c  :: Encoding 
   | 
||
| 
     transcode.c :: Encoding::Converter 
   | 
||
| 
     enc/*.c     :: encoding classes 
   | 
||
| 
     enc/trans/* :: codepoint mapping tables 
   | 
||
| 
     == goruby Interpreter Implementation 
   | 
||
| 
     === goruby Interpreter Implementation 
   | 
||
| 
       goruby.c 
   | 
||
| 
       golf_prelude.rb     : goruby specific libraries. 
   | 
||
| 
         -> golf_prelude.c : automatically generated 
   | 
||
| 
     = Appendix B. Ruby Extension API Reference 
   | 
||
| 
     == Appendix B. Ruby Extension API Reference 
   | 
||
| 
     == Types 
   | 
||
| 
     === Types 
   | 
||
| 
     VALUE :: 
   | 
||
| ... | ... | |
| 
       such as struct RString, etc.  To refer the values in structures, use 
   | 
||
| 
       casting macros like RSTRING(obj). 
   | 
||
| 
     == Variables and Constants 
   | 
||
| 
     === Variables and Constants 
   | 
||
| 
     Qnil :: 
   | 
||
| ... | ... | |
| 
       false object 
   | 
||
| 
     == C Pointer Wrapping 
   | 
||
| 
     === C Pointer Wrapping 
   | 
||
| 
     Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval) :: 
   | 
||
| ... | ... | |
| 
       This macro retrieves the pointer value from DATA, and assigns it to 
   | 
||
| 
       the variable sval. 
   | 
||
| 
     == Checking Data Types 
   | 
||
| 
     === Checking Data Types 
   | 
||
| 
     RB_TYPE_P(value, type) :: 
   | 
||
| ... | ... | |
| 
       Checks that +value+ is a String and is not tainted 
   | 
||
| 
     == Data Type Conversion 
   | 
||
| 
     === Data Type Conversion 
   | 
||
| 
     FIX2INT(value), INT2FIX(i) :: 
   | 
||
| ... | ... | |
| 
       char * -> String 
   | 
||
| 
     == Defining Classes and Modules 
   | 
||
| 
     === Defining Classes and Modules 
   | 
||
| 
     VALUE rb_define_class(const char *name, VALUE super) :: 
   | 
||
| ... | ... | |
| 
       Extend the object with the module's attributes. 
   | 
||
| 
     == Defining Global Variables 
   | 
||
| 
     === Defining Global Variables 
   | 
||
| 
     void rb_define_variable(const char *name, VALUE *var) :: 
   | 
||
| ... | ... | |
| 
       GC requires C global variables which hold Ruby values to be marked. 
   | 
||
| 
       rb_global_variable tells GC to protect these variables. 
   | 
||
| 
     == Constant Definition 
   | 
||
| 
     === Constant Definition 
   | 
||
| 
     void rb_define_const(VALUE klass, const char *name, VALUE val) :: 
   | 
||
| ... | ... | |
| 
         rb_define_const(rb_cObject, name, val) 
   | 
||
| 
     == Method Definition 
   | 
||
| 
     === Method Definition 
   | 
||
| 
     rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) :: 
   | 
||
| ... | ... | |
| 
       non-symbol keys, then they are copied to another hash and the new hash 
   | 
||
| 
       is stored through +original_hash+, else 0 is stored. 
   | 
||
| 
     == Invoking Ruby method 
   | 
||
| 
     === Invoking Ruby method 
   | 
||
| 
     VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) :: 
   | 
||
| ... | ... | |
| 
       Returns true if the object responds to the message specified by id. 
   | 
||
| 
     == Instance Variables 
   | 
||
| 
     === Instance Variables 
   | 
||
| 
     VALUE rb_iv_get(VALUE obj, const char *name) :: 
   | 
||
| ... | ... | |
| 
       Sets the value of the instance variable. 
   | 
||
| 
     == Control Structure 
   | 
||
| 
     === Control Structure 
   | 
||
| 
     VALUE rb_block_call(VALUE recv, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2) :: 
   | 
||
| ... | ... | |
| 
       return the given argument value.  This function never return to the 
   | 
||
| 
       caller. 
   | 
||
| 
     == Exceptions and Errors 
   | 
||
| 
     === Exceptions and Errors 
   | 
||
| 
     void rb_warn(const char *fmt, ...) :: 
   | 
||
| ... | ... | |
| 
     must be a VALUE).  Since it conflicts with "%i", for integers in 
   | 
||
| 
     format strings, use "%d". 
   | 
||
| 
     == Initialize and Start the Interpreter 
   | 
||
| 
     === Initialize and Start the Interpreter 
   | 
||
| 
     The embedding API functions are below (not needed for extension libraries): 
   | 
||
| ... | ... | |
| 
       Specifies the name of the script ($0). 
   | 
||
| 
     == Hooks for the Interpreter Events 
   | 
||
| 
     === Hooks for the Interpreter Events 
   | 
||
| 
     void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) :: 
   | 
||
| ... | ... | |
| 
       Removes the specified hook function. 
   | 
||
| 
     == Memory usage 
   | 
||
| 
     === Memory usage 
   | 
||
| 
     void rb_gc_adjust_memory_usage(ssize_t diff) :: 
   | 
||
| ... | ... | |
| 
       is decreased; a memory block is freed or a block is reallocated as 
   | 
||
| 
       smaller size.  This function may trigger the GC. 
   | 
||
| 
     == Macros for Compatibility 
   | 
||
| 
     === Macros for Compatibility 
   | 
||
| 
     Some macros to check API compatibilities are available by default. 
   | 
||
| ... | ... | |
| 
       Means that rb_add_event_hook() takes the third argument `data', to be 
   | 
||
| 
       passed to the given event hook function. 
   | 
||
| 
     = Appendix C. Functions available for use in extconf.rb 
   | 
||
| 
     == Appendix C. Functions available for use in extconf.rb 
   | 
||
| 
     See documentation for {mkmf}[rdoc-ref:MakeMakefile]. 
   | 
||
| 
     = Appendix D. Generational GC 
   | 
||
| 
     == Appendix D. Generational GC 
   | 
||
| 
     Ruby 2.1 introduced a generational garbage collector (called RGenGC). 
   | 
||
| 
     RGenGC (mostly) keeps compatibility. 
   | 
||
| ... | ... | |
| 
     be further improved. Especially, the "Don't touch pointers directly" section is 
   | 
||
| 
     important. 
   | 
||
| 
     == Incompatibility 
   | 
||
| 
     === Incompatibility 
   | 
||
| 
     You can't write RBASIC(obj)->klass field directly because it is const 
   | 
||
| 
     value now. 
   | 
||
| ... | ... | |
| 
       Reset RBasic::klass to be klass. 
   | 
||
| 
       We expect the `klass' is hidden class by rb_obj_hide(). 
   | 
||
| 
     == Write barriers 
   | 
||
| 
     === Write barriers 
   | 
||
| 
     RGenGC doesn't require write barriers to support generational GC. 
   | 
||
| 
     However, caring about write barrier can improve the performance of 
   | 
||
| 
     RGenGC. Please check the following tips. 
   | 
||
| 
     === Don't touch pointers directly 
   | 
||
| 
     ==== Don't touch pointers directly 
   | 
||
| 
     In MRI (include/ruby/ruby.h), some macros to acquire pointers to the 
   | 
||
| 
     internal data structures are supported such as RARRAY_PTR(), 
   | 
||
| ... | ... | |
| 
     DO NOT USE THESE MACROS and instead use the corresponding C-APIs such as 
   | 
||
| 
     rb_ary_aref(), rb_ary_store() and so on. 
   | 
||
| 
     === Consider whether to insert write barriers 
   | 
||
| 
     ==== Consider whether to insert write barriers 
   | 
||
| 
     You don't need to care about write barriers if you only use built-in 
   | 
||
| 
     types. 
   | 
||
| ... | ... | |
| 
     of overhead. Basically we don't recommend you insert write barriers. 
   | 
||
| 
     Please carefully consider the risks. 
   | 
||
| 
     === Combine with built-in types 
   | 
||
| 
     ==== Combine with built-in types 
   | 
||
| 
     Please consider utilizing built-in types. Most built-in types support 
   | 
||
| 
     write barrier, so you can use them to avoid manually inserting write 
   | 
||
| ... | ... | |
| 
     With use of such techniques, you don't need to insert write barriers 
   | 
||
| 
     anymore. 
   | 
||
| 
     === Insert write barriers 
   | 
||
| 
     ==== Insert write barriers 
   | 
||
| 
     \[AGAIN] Inserting write barriers is a very difficult hack, and it is 
   | 
||
| 
     easy to introduce critical bugs. And inserting write barriers has 
   | 
||
| ... | ... | |
| 
     For a complete guide for RGenGC and write barriers, please refer to 
   | 
||
| 
     <https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RGenGC>. 
   | 
||
| 
     = Appendix E. RB_GC_GUARD to protect from premature GC 
   | 
||
| 
     == Appendix E. RB_GC_GUARD to protect from premature GC 
   | 
||
| 
     C Ruby currently uses conservative garbage collection, thus VALUE 
   | 
||
| 
     variables must remain visible on the stack or registers to ensure any 
   | 
||