summaryrefslogtreecommitdiff
path: root/README.EXT
blob: efa627a24ad08862107b3f757f80ce5437fbfc8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
.\" README.EXT -  -*- Text -*- created at: Mon Aug  7 16:45:54 JST 1995

Rubyを拡張するための方法を解説する.

RubyはCコードを書くことによって,簡単に機能を追加できる.おおまかな手
順は以下の通りである.

  1. ファイルを用意する

     extディレクトリの下に拡張モジュール用のディレクトリを用意して,そ
     の配下に以下のファイルを用意する必要がある.

     + MANIFEST.必要なファイルの一覧.

       必ず必要.一時的なファイル以外の全てのファイル名を1行1ファイル
       の形式で記述すること.

     + Cのソースファイル.

       モジュールが1ファイルだけからなる時はモジュール名と同じ名前のファ
       イル名(モジュール.c)をつける.逆にモジュールが複数からなる時は
       モジュール名のついたソースファイルは避けること.

     + extconf.rb(optional).設定用ファイル.

       関数やライブラリ,ヘッダの存在チェックをしたり,モジュール名な
       どを設定する.このファイルが無ければ全てデフォルトでコンパイル
       される.

     + depend(optional).Makefileにインクルードするためのファ
       イルの依存関係を記述したファイル.

       `gcc -MM *.c > depend'とすれば自動的に生成できる.

  2. Cのソースファイルを用意する

     必ず「Init_モジュール名」という関数を用意し,その中で,変数やクラ
     スの定義や,クラスへのメソッドの登録などの初期化を行うこと.この
     関数の呼び出しはインタプリタの初期化時(静的リンクの場合)かモジュー
     ルのロード時(動的リンクの場合)に自動的に行われる.

* Ruby API

C言語からRubyの機能を利用するAPIは以下の通りである.

** 型

 VALUE

   Rubyオブジェクトを表現する型.必要に応じてキャストして用いる.組み
   込み型を表現するCの型はruby.hに記述してあるRで始まる構造体である.
   VALUE型をこれらにキャストするためにRで始まる構造体名を全て大文字に
   した名前のマクロが用意されている.

** 変数・定数

 Qnil

   定数: nilオブジェクト

 Qself

   変数: 現在のselfオブジェクトの値.一般にメソッドにはselfを指す引数
   が与えられるので, この変数にアクセスする必要はない.この変数の値を
   変更する時は以後のselfの値そのものが変わってしまうので, 特別な事情
   がない限り代入してはならない.

 TRUE

   定数: tオブジェクト(真のデフォルト値)

 FALSE

   定数: nilオブジェクト

** Cデータのカプセル化

 VALUE data_new(void *sval, void (*mark)(), void (*free)())

   Cの任意のポインタをカプセル化したrubyオブジェクトを返す.このポイン
   タがrubyからアクセスされなくなった時,freeで指定した関数が呼ばれる.
   また,このポインタの指すデータが他のrubyオブジェクトを指している場
   合,markに指定する関数でマークする必要がある.

 Make_Data_Struct(obj, iv, type, mark, free, sval)

   type型のメモリをmallocし,変数svalに代入した後,それをカプセル化し
   たデータをobjのインスタンス変数ivに代入するマクロ.

 Get_Data_Struct(obj, iv, type, sval)

   objのインスタンス変数ivが指すデータからtype型のポインタを取り出し
   変数svalに代入するマクロ.

** クラス/モジュール定義

 VALUE rb_define_class(char *name, VALUE super)

   superのサブクラスとして新しいRubyクラスを定義する.

 VALUE rb_define_module(char *name)

   新しいRubyモジュールを定義する.

 void rb_include_module(VALUE class, VALUE module)

   モジュールをインクルードする.classがすでにmoduleをインクルードして
   いる時には何もしない(多重インクルードの禁止).

 void rb_extend_object(VALUE object, VALUE module)

   オブジェクトをモジュール(で定義されているメソッド)で拡張する.

** 大域変数定義

 void rb_define_variable(char *name, VALUE *var)

   RubyとCとで共有するグローバル変数を定義する.変数名が`$'で始まらな
   い時には自動的に追加される.nameとしてrubyの識別子として許されない
   文字(例えば` ')を含む場合にはrubyプログラムからは見えなくなる.

 void rb_define_readonly_variable(char *name, VALUE *var)

   RubyとCとで共有するread onlyのグローバル変数を定義する.read onlyで
   あること以外はrb_define_variable()と同じ.

 void rb_define_virtual_variable(char *name,
				VALUE (*getter)(), VALUE (*setter)())

   関数によって実現されるRuby変数を定義する.変数が参照された時には
   getterが,関数に値がセットされた時にはsetterが呼ばれる.

 void rb_define_hooked_variable(char *name, VALUE *var,
				VALUE (*getter)(), VALUE (*setter)())

   関数によってhookのつけられたグローバル変数を定義する.変数が参照さ
   れた時にはgetterが,関数に値がセットされた時にはsetterが呼ばれる.
   getterやsetterに0を指定した時にはhookを指定しないのと同じ事になる.

 void rb_global_variable(VALUE *var)

   GCのため,Rubyプログラムからはアクセスされないが, Rubyオブジェクト
   を含む大域変数をマークする.

** クラス定数

 void rb_define_const(VALUE class, char *name, VALUE val)

   クラス定数を定義する.

** メソッド定義

 rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)

   メソッドを定義する.argcはselfを除く引数の数.argcが-1の時, 関数に
   は引数の数(selfを含まない)を第1引数, 引数の配列を第2引数とする形式
   で与えられる(第3引数はself).argcが-2の時, 引数はself, args(argsは
   引数を含むrubyの配列)という形式で与えられる.

 rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)

   privateメソッドを定義する.引数はrb_define_method()と同じ.

 rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)

   特異メソッドを定義する.引数はrb_define_method()と同じ.

 rb_scan_args(int atgc, VALUE *argv, char *fmt, ...)

   argc,argv形式で与えられた引数を分解する.fmtは必須引数の数, 付加引
   数の数, 残りの引数があるかを指定する文字列で, "数字数字*"という形式
   である. 2 番目の数字と"*"はそれぞれ省略可能である.必須引数が一つ
   もない場合は0を指定する.第3引数以降は変数へのポインタで, 該当する
   要素がその変数に格納される.付加引数に対応する引数が与えられていな
   い場合は変数にQnilが代入される.

** Rubyメソッド呼び出し

 VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)

   メソッド呼び出し.文字列からmidを得るためにはrb_intern()を使う.

 VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)

   メソッド呼び出し.引数をargc,argv形式で渡す.

 VALUE rb_eval_string(char *str)

   文字列をrubyとスクリプトしてコンパイル・実行する.

 ID rb_intern(char *name)

   文字列に対応するIDを返す.

 char *rb_id2name(ID id)

   IDに対応する文字列を返す(デバッグ用).

 char *rb_class2name(VALUE class)

   classの名前を返す(デバッグ用).classが名前を持たない時には, 一番近
   い名前を持つクラスの名前を返す.

** インスタンス変数

 VALUE rb_iv_get(VALUE obj, char *name)

   objのインスタンス変数の値を得る.`@'で始まらないインスタンス変数は 
   Rubyプログラムからアクセスできない「隠れた」インスタンス変数になる.

 VALUE rb_iv_set(VALUE obj, char *name, VALUE val)

   objのインスタンス変数をvalにセットする.

** 制御構造

 VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)

   func2をブロックとして設定し, func1をイテレータとして呼ぶ. func1に
   は arg1が引数として渡され, func2には第1引数にイテレータから与えられ
   た値, 第2引数にarg2が渡される.
 
 VALUE rb_yield(VALUE val)

   valを値としてイテレータブロックを呼び出す.

 VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)

   関数func1をarg1を引数に呼び出す.func1の実行中に例外が発生した時に
   は func2をarg2を引数として呼ぶ.戻り値は例外が発生しなかった時は
   func1の戻り値, 例外が発生した時にはfunc2の戻り値である.

 VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)

   関数func1をarg1を引数として実行し, 実行終了後(たとえ例外が発生して
   も) func2をarg2を引数として実行する.戻り値はfunc1の戻り値である(例
   外が発生した時は戻らない).

** 例外・エラー

 void Warning(char *fmt, ...)

   verbose時に標準エラー出力に警告情報を表示する.引数はprintf()と同じ.

 void Fail(char *fmt, ...)

   例外を発生させる.引数はprintf()と同じ.

 void Fatal(char *fmt, ...)

   致命的例外を発生させる.通常の例外処理は行なわれず, インタープリタ
   が終了する(ただしensureで指定されたコードは終了前に実行される).

 void Bug(char *fmt, ...)

   インタープリタなどプログラムのバグでしか発生するはずのない状況の時
   呼ぶ.インタープリタはコアダンプし直ちに終了する.例外処理は一切行
   なわれない.

** rubyの初期化・実行

Rubyをアプリケーションに埋め込む場合には以下のインタフェースを使う.通
常の拡張モジュールには必要ない.

 void ruby_init(int argc, char **argv, char **envp)

  rubyインタプリタの初期化を行なう.

 void ruby_run()

  rubyインタプリタを実行する.

 void ruby_script(char *name)

  rubyのスクリプト名($0)を設定する.

* extconf.rbの記述

拡張モジュールのディレクトリに`extconf.rb'というファイルが存在する時に
は,それが実行され,モジュールのコンパイルに必要な条件のチェックなどを
行う事が出来る.extconf.rbの中では以下の関数を使う事ができる.

 have_library(lib, func)

   関数funcを定義しているライブラリlibの存在をチェックする.ライブラリ
   が存在する時,TRUEを返す.

 have_func(func)

   関数funcの存在をチェックする.funcが標準ではリンクされないライブラ
   リ内のものである時には先にhave_libraryでそのライブラリをチェックし
   ておく事.関数が存在する時,TRUEを返す.

 have_header(header)

   ヘッダファイルの存在をチェックする.ヘッダファイルが存在する時TRUE
   を返す.

 create_makefile(target)

   拡張モジュール用のMakefileを生成する.この関数を呼ばなければそのモ
   ジュールはコンパイルされない.

/*
 * Local variables:
 * fill-column: 70
 * end:
 */