1# extension.ja.rdoc - -*- RDoc -*- created at: Mon Aug 7 16:45:54 JST 1995 2 3= Rubyの拡張ライブラリの作り方 4 5Rubyの拡張ライブラリの作り方を説明します. 6 7== 基礎知識 8 9Cの変数には型があり,データには型がありません.ですから,た 10とえばポインタをintの変数に代入すると,その値は整数として取 11り扱われます.逆にRubyの変数には型がなく,データに型がありま 12す.この違いのため,CとRubyは相互に変換しなければ,お互いの 13データをアクセスできません. 14 15RubyのデータはVALUEというCの型で表現されます.VALUE型のデー 16タはそのデータタイプを自分で知っています.このデータタイプと 17いうのはデータ(オブジェクト)の実際の構造を意味していて,Ruby 18のクラスとはまた違ったものです. 19 20VALUEからCにとって意味のあるデータを取り出すためには 21 221. VALUEのデータタイプを知る 232. VALUEをCのデータに変換する 24 25の両方が必要です.(1)を忘れると間違ったデータの変換が行われ 26て,最悪プログラムがcore dumpします. 27 28=== データタイプ 29 30Rubyにはユーザが使う可能性のある以下のタイプがあります. 31 32T_NIL :: nil 33T_OBJECT :: 通常のオブジェクト 34T_CLASS :: クラス 35T_MODULE :: モジュール 36T_FLOAT :: 浮動小数点数 37T_STRING :: 文字列 38T_REGEXP :: 正規表現 39T_ARRAY :: 配列 40T_HASH :: 連想配列 41T_STRUCT :: (Rubyの)構造体 42T_BIGNUM :: 多倍長整数 43T_FIXNUM :: Fixnum(31bitまたは63bit長整数) 44T_COMPLEX :: 複素数 45T_RATIONAL :: 有理数 46T_FILE :: 入出力 47T_TRUE :: 真 48T_FALSE :: 偽 49T_DATA :: データ 50T_SYMBOL :: シンボル 51 52その他に内部で利用されている以下のタイプがあります. 53 54 T_ICLASS 55 T_MATCH 56 T_UNDEF 57 T_NODE 58 T_ZOMBIE 59 60ほとんどのタイプはCの構造体で実装されています. 61 62=== VALUEのデータタイプをチェックする 63 64ruby.hではTYPE()というマクロが定義されていて,VALUEのデータ 65タイプを知ることが出来ます.TYPE()マクロは上で紹介したT_XXXX 66の形式の定数を返します.VALUEのデータタイプに応じて処理する 67場合には,TYPE()の値で分岐することになります. 68 69 switch (TYPE(obj)) { 70 case T_FIXNUM: 71 /* FIXNUMの処理 */ 72 break; 73 case T_STRING: 74 /* 文字列の処理 */ 75 break; 76 case T_ARRAY: 77 /* 配列の処理 */ 78 break; 79 default: 80 /* 例外を発生させる */ 81 rb_raise(rb_eTypeError, "not valid value"); 82 break; 83 } 84 85それとデータタイプをチェックして,正しくなければ例外を発生す 86る関数が用意されています. 87 88 void Check_Type(VALUE value, int type) 89 90この関数はvalueがtypeで無ければ,例外を発生させます.引数と 91して与えられたVALUEのデータタイプが正しいかどうかチェックす 92るためには,この関数を使います. 93 94FIXNUMとNILに関してはより高速な判別マクロが用意されています. 95 96 FIXNUM_P(obj) 97 NIL_P(obj) 98 99=== VALUEをCのデータに変換する 100 101データタイプがT_NIL,T_FALSE,T_TRUEである時,データはそれぞ 102れnil,false,trueです.このデータタイプのオブジェクトはひと 103つずつしか存在しません. 104 105データタイプがT_FIXNUMの時,これは31bitまたは63bitのサイズを 106持つ整数です.longのサイズが32bitのプラットフォームであれば 10731bitに,longのサイズが64bitのプラットフォームであれば63bit 108になります. FIXNUM を C の整数に変換するためにはマクロ 109「FIX2INT()」または「FIX2LONG()」を使います.これらのマクロ 110を使用する際には事前にデータタイプがFIXNUMであることを確認す 111る必要がありますが,比較的高速に変換を行うことができます.ま 112た,「FIX2LONG()」は例外を発生しませんが,「FIX2INT()」は変 113換結果がintのサイズに収まらない場合には例外を発生します. 114それから,FIXNUMに限らずRubyのデータを整数に変換する 115「NUM2INT()」および「NUM2LONG()」というマクロがあります.こ 116れらのマクロはデータタイプのチェック無しで使えます 117(整数に変換できない場合には例外が発生する).同様にチェック無し 118で使える変換マクロはdoubleを取り出す「NUM2DBL()」があります. 119 120char* を取り出す場合, StringValue() と StringValuePtr() 121を使います. 122StringValue(var) は var が String 123であれば何もせず,そうでなければ var を var.to_str() の結果 124に置き換えるマクロ,StringValuePtr(var) は同様に var を 125String に置き換えてから var のバイト列表現に対する char* を 126返すマクロです.var の内容を直接置き換える処理が入るので, 127var は lvalue である必要があります. 128また,StringValuePtr() に類似した StringValueCStr() というマ 129クロもあります.StringValueCStr(var) は var を String に置き 130換えてから var の文字列表現に対する char* を返します.返され 131る文字列の末尾には NUL 文字が付加されます.なお,途中に NUL 132文字が含まれる場合は ArgumentError が発生します. 133一方,StringValuePtr() では,末尾に NUL 文字がある保証はなく, 134途中に NUL 文字が含まれている可能性もあります. 135 136それ以外のデータタイプは対応するCの構造体があります.対応す 137る構造体のあるVALUEはそのままキャスト(型変換)すれば構造体の 138ポインタに変換できます. 139 140構造体は「struct RXxxxx」という名前でruby.hで定義されていま 141す.例えば文字列は「struct RString」です.実際に使う可能性が 142あるのは文字列と配列くらいだと思います. 143 144ruby.hでは構造体へキャストするマクロも「RXXXXX()」(全部大文 145字にしたもの)という名前で提供されています(例: RSTRING()).た 146だし、構造体への直接のアクセスはできるだけ避け,対応する 147rb_xxxx() といった関数を使うようにして下さい.例えば,配列の 148要素へアクセスする場合は,rb_ary_entry(ary, offset), 149rb_ary_store(ary, offset, obj) を利用するようにして下さい. 150 151構造体からデータを取り出すマクロが提供されています.文字列 152strの長さを得るためには「RSTRING_LEN(str)」とし,文字列strを 153char*として得るためには「RSTRING_PTR(str)」とします. 154 155Rubyの構造体を直接アクセスする時に気をつけなければならないこ 156とは,配列や文字列の構造体の中身は参照するだけで,直接変更し 157ないことです.直接変更した場合,オブジェクトの内容の整合性が 158とれなくなって,思わぬバグの原因になります. 159 160=== CのデータをVALUEに変換する 161 162VALUEの実際の構造は 163 164FIXNUMの場合 :: 165 166 1bit左シフトして,LSBを立てる. 167 168その他のポインタの場合 :: 169 170 そのままVALUEにキャストする. 171 172となっています.よって,LSBをチェックすればVALUEがFIXNUMかど 173うかわかるわけです(ポインタのLSBが立っていないことを仮定して 174いる). 175 176ですから,FIXNUM以外のRubyのオブジェクトの構造体は単にVALUE 177にキャストするだけでVALUEに変換出来ます.ただし,任意の構造 178体がVALUEにキャスト出来るわけではありません.キャストするの 179はRubyの知っている構造体(ruby.hで定義されているstruct RXxxx 180のもの)だけです. 181 182FIXNUMに関しては変換マクロを経由する必要があります.Cの整数 183からVALUEに変換するマクロは以下のものがあります.必要に応じ 184て使い分けてください. 185 186INT2FIX() :: もとの整数が31bitまたは63bit以内に収まる自信 187 がある時 188INT2NUM() :: 任意の整数からVALUEへ 189 190INT2NUM()は整数がFIXNUMの範囲に収まらない場合,Bignumに変換 191してくれます(が,少し遅い). 192 193=== Rubyのデータを操作する 194 195先程も述べた通り,Rubyの構造体をアクセスする時に内容の更新を 196行うことは勧められません.で,Rubyのデータを操作する時には 197Rubyが用意している関数を用いてください. 198 199ここではもっとも使われるであろう文字列と配列の生成/操作を行 200う関数をあげます(全部ではないです). 201 202==== 文字列に対する関数 203 204rb_str_new(const char *ptr, long len) :: 205 206 新しいRubyの文字列を生成する. 207 208rb_str_new2(const char *ptr) :: 209rb_str_new_cstr(const char *ptr) :: 210 211 Cの文字列からRubyの文字列を生成する.この関数の機能は 212 rb_str_new(ptr, strlen(ptr))と同等である. 213 214rb_str_new_literal(const char *ptr) :: 215 216 Cのリテラル文字列からRubyの文字列を生成する. 217 218rb_tainted_str_new(const char *ptr, long len) :: 219 220 汚染マークが付加された新しいRubyの文字列を生成する.外部 221 からのデータに基づく文字列には汚染マークが付加されるべき 222 である. 223 224rb_tainted_str_new2(const char *ptr) :: 225rb_tainted_str_new_cstr(const char *ptr) :: 226 227 Cの文字列から汚染マークが付加されたRubyの文字列を生成する. 228 229rb_str_append(VALUE str1, VALUE str2) :: 230 231 Rubyの文字列str1にRubyの文字列str2を追加する. 232 233rb_sprintf(const char *format, ...) :: 234rb_vsprintf(const char *format, va_list ap) :: 235 236 Cの文字列formatと続く引数をprintf(3)のフォーマットにしたがって 237 整形し,Rubyの文字列を生成する. 238 239 注意: "%"PRIsVALUEがObject#to_s('+'フラグが指定されている 240 ときはObject#inspect)を使ったVALUEの出力に利用できる.これ 241 は"%i"と衝突するため,整数には"%d"を使用すること. 242 243rb_str_cat(VALUE str, const char *ptr, long len) :: 244 245 Rubyの文字列strにlenバイトの文字列ptrを追加する. 246 247rb_str_cat2(VALUE str, const char* ptr) :: 248rb_str_cat_cstr(VALUE str, const char* ptr) :: 249 250 Rubyの文字列strにCの文字列ptrを追加する.この関数の機能は 251 rb_str_cat(str, ptr, strlen(ptr))と同等である. 252 253rb_str_catf(VALUE str, const char* format, ...) :: 254rb_str_vcatf(VALUE str, const char* format, va_list ap) :: 255 256 Cの文字列formatと続く引数をprintf(3)のフォーマットにしたがって 257 整形し,Rubyの文字列strに追加する.この関数の機能は,それぞれ 258 rb_str_append(str, rb_sprintf(format, ...)) や 259 rb_str_append(str, rb_vsprintf(format, ap)) と同等である. 260 261rb_enc_str_new(const char *ptr, long len, rb_encoding *enc) :: 262rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc) :: 263 264 指定されたエンコーディングでRubyの文字列を生成する. 265 266rb_enc_str_new_literal(const char *ptr, rb_encoding *enc) :: 267 268 Cのリテラル文字列から指定されたエンコーディングでRubyの文字列を生成する. 269 270rb_usascii_str_new(const char *ptr, long len) :: 271rb_usascii_str_new_cstr(const char *ptr) :: 272 273 エンコーディングがUS-ASCIIのRubyの文字列を生成する. 274 275rb_usascii_str_new_literal(const char *ptr) :: 276 277 Cのリテラル文字列からエンコーディングがUS-ASCIIのRubyの文字列を生成する. 278 279rb_utf8_str_new(const char *ptr, long len) :: 280rb_utf8_str_new_cstr(const char *ptr) :: 281 282 エンコーディングがUTF-8のRubyの文字列を生成する. 283 284rb_utf8_str_new_literal(const char *ptr) :: 285 286 Cのリテラル文字列からエンコーディングがUTF-8のRubyの文字列を生成する. 287 288rb_str_resize(VALUE str, long len) :: 289 290 Rubyの文字列のサイズをlenバイトに変更する.strの長さは前 291 以てセットされていなければならない.lenが元の長さよりも短 292 い時は,lenバイトを越えた部分の内容は捨てられる.lenが元 293 の長さよりも長い時は,元の長さを越えた部分の内容は保存さ 294 れないでゴミになるだろう.この関数の呼び出しによって 295 RSTRING_PTR(str)が変更されるかもしれないことに注意. 296 297rb_str_set_len(VALUE str, long len) :: 298 299 Rubyの文字列のサイズをlenバイトにセットする.strが変更可 300 能でなければ例外が発生する.RSTRING_LEN(str)とは無関係に, 301 lenバイトまでの内容は保存される.lenはstrの容量を越えてい 302 てはならない. 303 304==== 配列に対する関数 305 306rb_ary_new() :: 307 308 要素が0の配列を生成する. 309 310rb_ary_new2(long len) :: 311rb_ary_new_capa(long len) :: 312 313 要素が0の配列を生成する.len要素分の領域をあらかじめ割り 314 当てておく. 315 316rb_ary_new3(long n, ...) :: 317rb_ary_new_from_args(long n, ...) :: 318 319 引数で指定したn要素を含む配列を生成する. 320 321rb_ary_new4(long n, VALUE *elts) :: 322rb_ary_new_from_values(long n, VALUE *elts) :: 323 324 配列で与えたn要素の配列を生成する. 325 326rb_ary_to_ary(VALUE obj) :: 327 328 オブジェクトを配列に変換する. 329 Object#to_aryと同等である. 330 331他にも配列を操作する関数が多数ある. これらは 332引数aryに配列を渡さなければならない. さもないと 333コアを吐く. 334 335rb_ary_aref(int argc, const VALUE *argv, VALUE ary) :: 336 337 Array#[]と同等. 338 339rb_ary_entry(VALUE ary, long offset) :: 340 341 \ary[offset] 342 343rb_ary_store(VALUE ary, long offset, VALUE obj) :: 344 345 \ary[offset] = obj 346 347rb_ary_subseq(VALUE ary, long beg, long len) :: 348 349 ary[beg, len] 350 351rb_ary_push(VALUE ary, VALUE val) :: 352rb_ary_pop(VALUE ary) :: 353rb_ary_shift(VALUE ary) :: 354rb_ary_unshift(VALUE ary, VALUE val) :: 355 356 ary.push, ary.pop, ary.shift, ary.unshift 357 358rb_ary_cat(VALUE ary, const VALUE *ptr, long len) :: 359 360 配列aryにptrからlen個のオブジェクトを追加する. 361 362== Rubyの機能を使う 363 364原理的にRubyで書けることはCでも書けます.RubyそのものがCで記 365述されているんですから,当然といえば当然なんですけど.ここで 366はRubyの拡張に使うことが多いだろうと予測される機能を中心に紹 367介します. 368 369=== Rubyに機能を追加する 370 371Rubyで提供されている関数を使えばRubyインタプリタに新しい機能 372を追加することができます.Rubyでは以下の機能を追加する関数が 373提供されています. 374 375- クラス,モジュール 376- メソッド,特異メソッドなど 377- 定数 378 379では順に紹介します. 380 381==== クラス/モジュール定義 382 383クラスやモジュールを定義するためには,以下の関数を使います. 384 385 VALUE rb_define_class(const char *name, VALUE super) 386 VALUE rb_define_module(const char *name) 387 388これらの関数は新しく定義されたクラスやモジュールを返します. 389メソッドや定数の定義にこれらの値が必要なので,ほとんどの場合 390は戻り値を変数に格納しておく必要があるでしょう. 391 392クラスやモジュールを他のクラスの内部にネストして定義する時に 393は以下の関数を使います. 394 395 VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) 396 VALUE rb_define_module_under(VALUE outer, const char *name) 397 398==== メソッド/特異メソッド定義 399 400メソッドや特異メソッドを定義するには以下の関数を使います. 401 402 void rb_define_method(VALUE klass, const char *name, 403 VALUE (*func)(ANYARGS), int argc) 404 405 void rb_define_singleton_method(VALUE object, const char *name, 406 VALUE (*func)(ANYARGS), int argc) 407 408念のため説明すると「特異メソッド」とは,その特定のオブジェク 409トに対してだけ有効なメソッドです.RubyではよくSmalltalkにお 410けるクラスメソッドとして,クラスに対する特異メソッドが使われ 411ます. 412 413これらの関数の argcという引数はCの関数へ渡される引数の数(と 414形式)を決めます.argcが0以上の時は関数に引き渡す引数の数を意 415味します.16個以上の引数は使えません(が,要りませんよね,そ 416んなに).実際の関数には先頭の引数としてselfが与えられますの 417で,指定した数より1多い引数を持つことになります. 418 419argcが負の時は引数の数ではなく,形式を指定したことになります. 420argcが-1の時は引数を配列に入れて渡されます.argcが-2の時は引 421数はRubyの配列として渡されます. 422 423メソッドを定義する関数はまだいくつかあります. ひとつはメソッド 424名としてIDを取ります. IDについては2.2.2を参照. 425 426 void rb_define_method_id(VALUE klass, ID name, 427 VALUE (*func)(ANYARGS), int argc) 428 429private/protectedなメソッドを定義するふたつの関数があります. 430 431 void rb_define_private_method(VALUE klass, const char *name, 432 VALUE (*func)(ANYARGS), int argc) 433 void rb_define_protected_method(VALUE klass, const char *name, 434 VALUE (*func)(ANYARGS), int argc) 435 436privateメソッドとは関数形式でしか呼び出すことの出来ないメソッ 437ドです. 438 439最後に, rb_define_module関数はモジュール関数を定義します. 440モジュール関数とはモジュールの特異メソッドであり,同時に 441privateメソッドでもあるものです.例をあげるとMathモジュール 442のsqrt()などがあげられます.このメソッドは 443 444 Math.sqrt(4) 445 446という形式でも 447 448 include Math 449 sqrt(4) 450 451という形式でも使えます.モジュール関数を定義する関数は以下の 452通りです. 453 454 void rb_define_module_function(VALUE module, const char *name, 455 VALUE (*func)(ANYARGS), int argc) 456 457関数的メソッド(Kernelモジュールのprivate method)を定義するた 458めの関数は以下の通りです. 459 460 void rb_define_global_function(const char *name, VALUE (*func)(ANYARGS), int argc) 461 462メソッドの別名を定義するための関数は以下の通りです. 463 464 void rb_define_alias(VALUE module, const char* new, const char* old); 465 466属性の取得・設定メソッドを定義するには 467 468 void rb_define_attr(VALUE klass, const char *name, int read, int write) 469 470クラスメソッドallocateを定義したり削除したりするための関数は 471以下の通りです. 472 473 void rb_define_alloc_func(VALUE klass, VALUE (*func)(VALUE klass)); 474 void rb_undef_alloc_func(VALUE klass); 475 476funcはクラスを引数として受け取って,新しく割り当てられたイン 477スタンスを返さなくてはなりません.このインスタンスは,外部リ 478ソースなどを含まない,できるだけ「空」のままにしておいたほう 479がよいでしょう. 480 481継承したクラスにある既存のメソッドをオーバーライドしているな 482ら,オーバーライドされたメソッドを呼び出すには以下の関数を使 483います. 484 485 VALUE rb_call_super(int argc, const VALUE *argv) 486 487現在のスコープのレシーバは(他に方法がなければ),以下の関数で 488得ることができます. 489 490 VALUE rb_current_receiver(void) 491 492==== 定数定義 493 494拡張ライブラリが必要な定数はあらかじめ定義しておいた方が良い 495でしょう.定数を定義する関数は二つあります. 496 497 void rb_define_const(VALUE klass, const char *name, VALUE val) 498 void rb_define_global_const(const char *name, VALUE val) 499 500前者は特定のクラス/モジュールに属する定数を定義するもの,後 501者はグローバルな定数を定義するものです. 502 503=== Rubyの機能をCから呼び出す 504 505既に『1.5 Rubyのデータを操作する』で一部紹介したような関数を 506使えば,Rubyの機能を実現している関数を直接呼び出すことが出来 507ます. 508 509# このような関数の一覧表はいまのところありません.ソースを見 510# るしかないですね. 511 512それ以外にもRubyの機能を呼び出す方法はいくつかあります. 513 514==== Rubyのプログラムをevalする 515 516CからRubyの機能を呼び出すもっとも簡単な方法として,文字列で 517与えられたRubyのプログラムを評価する以下の関数があります. 518 519 VALUE rb_eval_string(const char *str) 520 521この評価は現在の環境で行われます.つまり,現在のローカル変数 522などを受け継ぎます. 523 524評価は例外を発生するかもしれないことに注意しましょう. より安全 525な関数もあります. 526 527 VALUE rb_eval_string_protect(const char *str, int *state) 528 529この関数はエラーが発生するとnilを返します.そして,成功時には 530*stateはゼロに,さもなくば非ゼロになります. 531 532==== IDまたはシンボル 533 534Cから文字列を経由せずにRubyのメソッドを呼び出すこともできま 535す.その前に,Rubyインタプリタ内でメソッドや変数名を指定する 536時に使われているIDについて説明しておきましょう. 537 538IDとは変数名,メソッド名を表す整数です.Rubyの中では 539 540 :識別子 541 542または 543 544 :"任意の文字列" 545 546でアクセスできます.Cからこの整数を得るためには関数 547 548 rb_intern(const char *name) 549 rb_intern_str(VALUE name) 550 551を使います.Rubyから引数として与えられたシンボル(または文字 552列)をIDに変換するには以下の関数を使います. 553 554 rb_to_id(VALUE symbol) 555 rb_check_id(volatile VALUE *name) 556 rb_check_id_cstr(const char *name, long len, rb_encoding *enc) 557 558もし引数がシンボルでも文字列でもなければ,to_strメソッドで文 559字列に変換しようとします.第二の関数はその変換結果を*nameに保 560存し,その名前が既知のシンボルでない場合は0を返します.この関 561数が0以外を返した場合は*nameは常にシンボルか文字列であり,0を 562返した場合は常に文字列です.第三の関数はRubyの文字列ではなく 563NUL終端されたCの文字列を使います. 564 565Rubyから引数として与えられたシンボル(または文字列)をシンボル 566に変換するには以下の関数を使います. 567 568 rb_to_symbol(VALUE name) 569 rb_check_symbol(volatile VALUE *namep) 570 rb_check_symbol_cstr(const char *ptr, long len, rb_encoding *enc) 571 572これらの関数は,IDの代わりにシンボルを返すことを除けば上記の 573関数と同じです. 574 575==== CからRubyのメソッドを呼び出す 576 577Cから文字列を経由せずにRubyのメソッドを呼び出すためには以下 578の関数を使います. 579 580 VALUE rb_funcall(VALUE recv, ID mid, int argc, ...) 581 582この関数はオブジェクトrecvのmidで指定されるメソッドを呼び出 583します.その他に引数の指定の仕方が違う以下の関数もあります. 584 585 VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) 586 VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv) 587 VALUE rb_apply(VALUE recv, ID mid, VALUE args) 588 589applyには引数としてRubyの配列を与えます. 590 591==== 変数/定数を参照/更新する 592 593Cから関数を使って参照・更新できるのは,定数,インスタンス変 594数です.大域変数は一部のものはCの大域変数としてアクセスでき 595ます.ローカル変数を参照する方法は公開していません. 596 597オブジェクトのインスタンス変数を参照・更新する関数は以下の通 598りです. 599 600 VALUE rb_ivar_get(VALUE obj, ID id) 601 VALUE rb_ivar_set(VALUE obj, ID id, VALUE val) 602 603idはrb_intern()で得られるものを使ってください. 604 605定数を参照するには以下の関数を使ってください. 606 607 VALUE rb_const_get(VALUE obj, ID id) 608 609定数を新しく定義するためには『2.1.3 定数定義』で紹介さ 610れている関数を使ってください. 611 612== RubyとCとの情報共有 613 614C言語とRubyの間で情報を共有する方法について解説します. 615 616=== Cから参照できるRubyの定数 617 618以下のRubyの定数はCのレベルから参照できます. 619 620Qtrue :: 621Qfalse :: 622 623 真偽値.QfalseはC言語でも偽とみなされます(つまり0). 624 625Qnil :: 626 627 C言語から見た「nil」. 628 629=== CとRubyで共有される大域変数 630 631CとRubyで大域変数を使って情報を共有できます.共有できる大域 632変数にはいくつかの種類があります.そのなかでもっとも良く使わ 633れると思われるのはrb_define_variable()です. 634 635 void rb_define_variable(const char *name, VALUE *var) 636 637この関数はRubyとCとで共有する大域変数を定義します.変数名が 638`$'で始まらない時には自動的に追加されます.この変数の値を変 639更すると自動的にRubyの対応する変数の値も変わります. 640 641またRuby側からは更新できない変数もあります.このread onlyの 642変数は以下の関数で定義します. 643 644 void rb_define_readonly_variable(const char *name, VALUE *var) 645 646これら変数の他にhookをつけた大域変数を定義できます.hook付き 647の大域変数は以下の関数を用いて定義します.hook付き大域変数の 648値の参照や設定はhookで行う必要があります. 649 650 void rb_define_hooked_variable(const char *name, VALUE *var, 651 VALUE (*getter)(), void (*setter)()) 652 653この関数はCの関数によってhookのつけられた大域変数を定義しま 654す.変数が参照された時には関数getterが,変数に値がセットされ 655た時には関数setterが呼ばれる.hookを指定しない場合はgetterや 656setterに0を指定します. 657-- 658getterもsetterも0ならばrb_define_variable()と同じになる. 659++ 660 661getterとsetterの仕様は次の通りです. 662 663 VALUE (*getter)(ID id, VALUE *var); 664 void (*setter)(VALUE val, ID id, VALUE *var); 665 666それから,対応するCの変数を持たないRubyの大域変数を定義する 667こともできます. その変数の値はフック関数のみによって取得・設定 668されます. 669 670 void rb_define_virtual_variable(const char *name, 671 VALUE (*getter)(), void (*setter)()) 672 673この関数によって定義されたRubyの大域変数が参照された時には 674getterが,変数に値がセットされた時にはsetterが呼ばれます. 675 676getterとsetterの仕様は以下の通りです. 677 678 (*getter)(ID id); 679 (*setter)(VALUE val, ID id); 680 681=== CのデータをRubyオブジェクトにする 682 683Cの世界で定義されたデータ(構造体)をRubyのオブジェクトとして 684取り扱いたい場合がありえます.このような場合はTypedData_XXX 685マクロ群を用いて構造体へのポインタとRubyのオブジェクトとを互 686いに変換できます. 687 688-- 689古い(非Typedな)Data_XXXマクロ群は非推奨になりました. 690将来のバージョンのRubyでは古いマクロは動作しなくなる可能性 691があります. 692++ 693 694==== 構造体からオブジェクトへ 695 696構造体へのポインタsvalをRubyオブジェクトに変換するには次のマ 697クロを使います。 698 699 TypedData_Wrap_Struct(klass, data_type, sval) 700 701このマクロの戻り値は生成されたオブジェクトを表すVALUE値です. 702 703klassはこのオブジェクトのクラスです.data_typeはこの構造体を 704Rubyが管理するための情報を記述したconst rb_data_type_t型への 705ポインタです. 706 707なお, klassは, Objectや他のクラスではなくData (rb_cData)とい 708う特別なクラスから派生することが推奨されます. 709Dataから派生しない場合には, 必ずrb_undef_alloc_func(klass) 710を呼び出してください. 711 712rb_data_type_tは次のように定義されています. 713 714 typedef struct rb_data_type_struct rb_data_type_t; 715 716 struct rb_data_type_struct { 717 const char *wrap_struct_name; 718 struct { 719 void (*dmark)(void*); 720 void (*dfree)(void*); 721 size_t (*dsize)(const void *); 722 void *reserved[2]; 723 } function; 724 const rb_data_type_t *parent; 725 void *data; 726 VALUE flags; 727 }; 728 729wrap_struct_nameはこの構造体を識別する名前です.主に統計情報 730の収集と出力に用いられます.プロセス内で一意であれば特にCや 731Rubyの識別子として有効である必要はありません. 732 733dmarkおよびdfree関数はGC実行中に呼び出されます. 734なお, GC実行中はRubyオブジェクトのアロケーションは禁止されま 735す. よって, dmarkおよびdfree関数でRubyオブジェクトのアロケー 736ションは行わないでください. 737 738dmarkはガーベージコレクタがオブジェクトへの参照をマークする 739ときに用いる関数です.この構造体がRubyのオブジェクトへの参照 740を保持するときには, dmarkではrb_gc_markなどを用いて構造体内 741のすべての参照をマークしなければなりません. 742そのような参照を含まない時には0を指定します. 743 744-- 745そのような参照は勧められません. 746++ 747 748dfreeはこの構造体がもう不要になった時に呼ばれる関数です.こ 749の関数がガーベージコレクタから呼ばれます.これが-1の場合は, 750単純に構造体が解放されます. 751 752dsizeは構造体が消費しているメモリのバイト数を返す関数です. 753引数として構造体へのポインタが渡されます.実装困難であれば0 754を渡しても差し支えありませんが, できるだけ指定するようにして 755ください. 756 757reservedとparentは0で埋めなければなりません. 758 759dataにはユーザー定義の任意の値を指定できます.Rubyはこの値に 760は関知しないので,好きに使ってください. 761 762flagsには次のフラグのうち当てはまるもののビット和を指定しま 763す.いずれもRubyのガーベージコレクタについての深い理解を必要 764としますので,良くわからない場合には0を指定すると良いでしょ 765う. 766 767RUBY_TYPED_FREE_IMMEDIATELY :: 768 769 このフラグを指定すると,ガーベージコレクタはこの構造体が不 770 要になった場合にはGC中に直ちにdfreeを呼び出します. 771 dfreeがRuby内部のロック(GVL)を解放する可能性がない場合はこ 772 のフラグを指定できます. 773 774 指定しない場合はdfree呼び出しは遅延され, ファイナライザと 775 同じタイミングで実行されます. 776 777RUBY_TYPED_WB_PROTECTED :: 778 779 オブジェクトの実装がライトバリアをサポートしていることを示 780 します.このフラグを指定するとRubyはそのオブジェクトに対し 781 てGCをより効率的に実行できます. 782 ただし,指定する場合はユーザーはそのオブジェクトのすべての 783 メソッドの実装に適切にライトバリアを挿入する責任があります. 784 さもなくばRubyは実行時にクラッシュする可能性があります. 785 786 ライトバリアについてはdoc/extension.ja.rdocのAppendix D 787 "世代別GC"も参照してください. 788 789 790Cの構造体の割当と対応するオブジェクトの生成を同時に行うマク 791ロとして以下のものが提供されています. 792 793 TypedData_Make_Struct(klass, type, data_type, sval) 794 795このマクロの戻り値は生成されたオブジェクトのVALUE値 796です.このマクロは以下の式のように働きます: 797 798 (sval = ZALLOC(type), TypedData_Wrap_Struct(klass, data_type, sval)) 799 800klass, data_typeはData_Wrap_Structと同じ働きをします.type 801は割り当てるC構造体の型です.割り当てられた構造体は変数sval 802に代入されます.この変数の型は (type*) である必要があります. 803 804==== オブジェクトから構造体へ 805 806TypedData_Wrap_StructやTypedData_Make_Structで生成したオブジェ 807クトから構造体へのポインタを復元するには以下のマクロを用いま 808す. 809 810 TypedData_Get_Struct(obj, type, &data_type, sval) 811 812Cの構造体へのポインタは変数svalに代入されます. 813 814これらのマクロの使い方はちょっと分かりにくいので,後で説明す 815る例題を参照してください. 816 817== 例: dbmの拡張ライブラリの作成 818 819=== ディレクトリを作る 820 821 % mkdir ext/dbm 822 823Ruby 1.1からは任意のディレクトリでダイナミックライブラリを作 824ることができるようになりました.Rubyに静的にリンクする場合に 825はRubyを展開したディレクトリの下,extディレクトリの中に拡張 826ライブラリ用のディレクトリを作る必要があります.名前は適当に 827選んで構いません. 828 829=== 設計する 830 831まあ,当然なんですけど,どういう機能を実現するかどうかまず設 832計する必要があります.どんなクラスをつくるか,そのクラスには 833どんなメソッドがあるか,クラスが提供する定数などについて設計 834します. 835 836=== Cコードを書く 837 838拡張ライブラリ本体となるC言語のソースを書きます.C言語のソー 839スがひとつの時には「ライブラリ名.c」を選ぶと良いでしょう.C 840言語のソースが複数の場合には逆に「ライブラリ名.c」というファ 841イル名は避ける必要があります.オブジェクトファイルとモジュー 842ル生成時に中間的に生成される「ライブラリ名.o」というファイル 843とが衝突するからです.また,後述する mkmf ライブラリのいくつ 844かの関数がコンパイルを要するテストのために「conftest.c」とい 845うファイル名を使用することに注意してください.ソースファイル 846名として「conftest.c」を使用してはなりません. 847 848Rubyは拡張ライブラリをロードする時に「Init_ライブラリ名」と 849いう関数を自動的に実行します.dbmライブラリの場合「Init_dbm」 850です.この関数の中でクラス,モジュール,メソッド,定数などの 851定義を行います.dbm.cから一部引用します. 852 853 void 854 Init_dbm(void) 855 { 856 /* DBMクラスを定義する */ 857 VALUE cDBM = rb_define_class("DBM", rb_cObject); 858 /* DBMはEnumerableモジュールをインクルードする */ 859 rb_include_module(cDBM, rb_mEnumerable); 860 861 /* DBMクラスのクラスメソッドopen(): 引数はCの配列で受ける */ 862 rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1); 863 864 /* DBMクラスのメソッドclose(): 引数はなし */ 865 rb_define_method(cDBM, "close", fdbm_close, 0); 866 /* DBMクラスのメソッド[]: 引数は1個 */ 867 rb_define_method(cDBM, "[]", fdbm_fetch, 1); 868 869 /* ... */ 870 871 /* DBMデータを格納するインスタンス変数名のためのID */ 872 id_dbm = rb_intern("dbm"); 873 } 874 875DBMライブラリはdbmのデータと対応するオブジェクトになるはずで 876すから,Cの世界のdbmをRubyの世界に取り込む必要があります. 877 878dbm.cではTypedData_Make_Structを以下のように使っています. 879 880 struct dbmdata { 881 int di_size; 882 DBM *di_dbm; 883 }; 884 885 static const rb_data_type_t dbm_type = { 886 "dbm", 887 {0, free_dbm, memsize_dbm,}, 888 0, 0, 889 RUBY_TYPED_FREE_IMMEDIATELY, 890 }; 891 892 obj = TypedData_Make_Struct(klass, struct dbmdata, &dbm_type, dbmp); 893 894ここではdbmdata構造体へのポインタをDataにカプセル化してい 895ます.DBM*を直接カプセル化しないのはclose()した時の処理を考 896えてのことです. 897 898Dataオブジェクトからdbmstruct構造体のポインタを取り出すため 899に以下のマクロを使っています. 900 901 #define GetDBM(obj, dbmp) do {\ 902 TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\ 903 if ((dbmp) == 0) closed_dbm();\ 904 if ((dbmp)->di_dbm == 0) closed_dbm();\ 905 } while (0) 906 907ちょっと複雑なマクロですが,要するにdbmdata構造体のポインタ 908の取り出しと,closeされているかどうかのチェックをまとめてい 909るだけです. 910 911DBMクラスにはたくさんメソッドがありますが,分類すると3種類の 912引数の受け方があります.ひとつは引数の数が固定のもので,例と 913してはdeleteメソッドがあります.deleteメソッドを実装している 914fdbm_delete()はこのようになっています. 915 916 static VALUE 917 fdbm_delete(VALUE obj, VALUE keystr) 918 { 919 /* ... */ 920 } 921 922引数の数が固定のタイプは第1引数がself,第2引数以降がメソッド 923の引数となります. 924 925引数の数が不定のものはCの配列で受けるものとRubyの配列で受け 926るものとがあります.dbmライブラリの中で,Cの配列で受けるもの 927はDBMのクラスメソッドであるopen()です.これを実装している関 928数fdbm_s_open()はこうなっています. 929 930 static VALUE 931 fdbm_s_open(int argc, VALUE *argv, VALUE klass) 932 { 933 /* ... */ 934 935 if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) { 936 mode = 0666; /* default value */ 937 } 938 939 /* ... */ 940 } 941 942このタイプの関数は第1引数が与えられた引数の数,第2引数が与え 943られた引数の入っている配列になります.selfは第3引数として与 944えられます. 945 946この配列で与えられた引数を解析するための関数がopen()でも使わ 947れているrb_scan_args()です.第3引数に指定したフォーマットに従 948い,第4引数以降に指定したVALUEへの参照に値を代入してくれま 949す. 950 951引数の数をチェックするだけならrb_check_arity()が使えます. 952これは引数をリストとして扱いたいときに便利です. 953 954引数をRubyの配列として受け取るメソッドの例には 955Thread#initializeがあります.実装はこうです. 956 957 static VALUE 958 thread_initialize(VALUE thread, VALUE args) 959 { 960 /* ... */ 961 } 962 963第1引数はself,第2引数はRubyの配列です. 964 965*注意事項* 966 967Rubyと共有はしないがRubyのオブジェクトを格納する可能性のある 968Cの大域変数は以下の関数を使ってRubyインタプリタに変数の存在 969を教えてあげてください.でないとGCでトラブルを起こします. 970 971 void rb_global_variable(VALUE *var) 972 973=== extconf.rbを用意する 974 975Makefileを作る場合の雛型になるextconf.rbというファイルを作り 976ます.extconf.rbはライブラリのコンパイルに必要な条件のチェッ 977クなどを行うことが目的です.まず, 978 979 require 'mkmf' 980 981をextconf.rbの先頭に置きます.extconf.rbの中では以下のRuby関 982数を使うことが出来ます. 983 984 have_library(lib, func): ライブラリの存在チェック 985 have_func(func, header): 関数の存在チェック 986 have_header(header): ヘッダファイルの存在チェック 987 create_makefile(target[, target_prefix]): Makefileの生成 988 989以下の変数を使うことができます. 990 991 $CFLAGS: コンパイル時に追加的に指定するフラグ(-Oなど) 992 $CPPFLAGS: プリプロセッサに追加的に指定するフラグ(-Iや-Dなど) 993 $LDFLAGS: リンク時に追加的に指定するフラグ(-Lなど) 994 $objs: リンクされるオブジェクトファイル名のリスト 995 996オブジェクトファイルのリストは,通常はソースファイルを検索し 997て自動的に生成されますが,makeの途中でソースを生成するような 998場合は明示的に指定する必要があります. 999 1000ライブラリをコンパイルする条件が揃わず,そのライブラリをコン 1001パイルしない時にはcreate_makefileを呼ばなければMakefileは生 1002成されず,コンパイルも行われません. 1003 1004=== dependを用意する 1005 1006もし,ディレクトリにdependというファイルが存在すれば, 1007Makefileが依存関係をチェックしてくれます. 1008 1009 % gcc -MM *.c > depend 1010 1011などで作ることが出来ます.あって損は無いでしょう. 1012 1013=== Makefileを生成する 1014 1015Makefileを実際に生成するためには 1016 1017 ruby extconf.rb 1018 1019とします.extconf.rbに require 'mkmf' の行がない場合にはエラー 1020になりますので,引数を追加して 1021 1022 ruby -r mkmf extconf.rb 1023 1024としてください. 1025 1026site_ruby ディレクトリでなく, 1027vendor_ruby ディレクトリにインストールする場合には 1028以下のように --vendor オプションを加えてください. 1029 1030 ruby extconf.rb --vendor 1031 1032ディレクトリをext以下に用意した場合にはRuby全体のmakeの時に 1033自動的にMakefileが生成されますので,このステップは不要です. 1034 1035=== makeする 1036 1037動的リンクライブラリを生成する場合にはその場でmakeしてくださ 1038い.必要であれば make install でインストールされます. 1039 1040ext以下にディレクトリを用意した場合は,Rubyのディレクトリで 1041makeを実行するとMakefileを生成からmake,必要によってはそのモ 1042ジュールのRubyへのリンクまで自動的に実行してくれます. 1043extconf.rbを書き換えるなどしてMakefileの再生成が必要な時はま 1044たRubyディレクトリでmakeしてください. 1045 1046拡張ライブラリはmake installでRubyライブラリのディレクトリの 1047下にコピーされます.もし拡張ライブラリと協調して使うRubyで記 1048述されたプログラムがあり,Rubyライブラリに置きたい場合には, 1049拡張ライブラリ用のディレクトリの下に lib というディレクトリ 1050を作り,そこに 拡張子 .rb のファイルを置いておけば同時にイン 1051ストールされます. 1052 1053=== デバッグ 1054 1055まあ,デバッグしないと動かないでしょうね.ext/Setupにディレ 1056クトリ名を書くと静的にリンクするのでデバッガが使えるようにな 1057ります.その分コンパイルが遅くなりますけど. 1058 1059=== できあがり 1060 1061後はこっそり使うなり,広く公開するなり,売るなり,ご自由にお 1062使いください.Rubyの作者は拡張ライブラリに関して一切の権利を 1063主張しません. 1064 1065== Appendix A. Rubyのソースコードの分類 1066 1067Rubyのソースはいくつかに分類することが出来ます.このうちクラ 1068スライブラリの部分は基本的に拡張ライブラリと同じ作り方になっ 1069ています.これらのソースは今までの説明でほとんど理解できると 1070思います. 1071 1072=== Ruby言語のコア 1073 1074class.c :: クラスとモジュール 1075error.c :: 例外クラスと例外機構 1076gc.c :: 記憶領域管理 1077load.c :: ライブラリのロード 1078object.c :: オブジェクト 1079variable.c :: 変数と定数 1080 1081=== Rubyの構文解析器 1082 1083parse.y :: 字句解析器と構文定義 1084parse.c :: 自動生成 1085defs/keywords :: 予約語 1086lex.c :: 自動生成 1087 1088=== Rubyの評価器 (通称YARV) 1089 1090 compile.c 1091 eval.c 1092 eval_error.c 1093 eval_jump.c 1094 eval_safe.c 1095 insns.def : 仮想機械語の定義 1096 iseq.c : VM::ISeqの実装 1097 thread.c : スレッド管理とコンテキスト切り替え 1098 thread_win32.c : スレッド実装 1099 thread_pthread.c : 同上 1100 vm.c 1101 vm_dump.c 1102 vm_eval.c 1103 vm_exec.c 1104 vm_insnhelper.c 1105 vm_method.c 1106 1107 defs/opt_insns_unif.def : 命令融合 1108 defs/opt_operand.def : 最適化のための定義 1109 1110 -> insn*.inc : 自動生成 1111 -> opt*.inc : 自動生成 1112 -> vm.inc : 自動生成 1113 1114=== 正規表現エンジン (鬼車) 1115 1116 regex.c 1117 regcomp.c 1118 regenc.c 1119 regerror.c 1120 regexec.c 1121 regparse.c 1122 regsyntax.c 1123 1124=== ユーティリティ関数 1125 1126debug.c :: Cデバッガ用のデバッグシンボル 1127dln.c :: 動的ローディング 1128st.c :: 汎用ハッシュ表 1129strftime.c :: 時刻整形 1130util.c :: その他のユーティリティ 1131 1132=== Rubyコマンドの実装 1133 1134 dmyext.c 1135 dmydln.c 1136 dmyencoding.c 1137 id.c 1138 inits.c 1139 main.c 1140 ruby.c 1141 version.c 1142 1143 gem_prelude.rb 1144 prelude.rb 1145 1146=== クラスライブラリ 1147 1148array.c :: Array 1149bignum.c :: Bignum 1150compar.c :: Comparable 1151complex.c :: Complex 1152cont.c :: Fiber, Continuation 1153dir.c :: Dir 1154enum.c :: Enumerable 1155enumerator.c :: Enumerator 1156file.c :: File 1157hash.c :: Hash 1158io.c :: IO 1159marshal.c :: Marshal 1160math.c :: Math 1161numeric.c :: Numeric, Integer, Fixnum, Float 1162pack.c :: Array#pack, String#unpack 1163proc.c :: Binding, Proc 1164process.c :: Process 1165random.c :: 乱数 1166range.c :: Range 1167rational.c :: Rational 1168re.c :: Regexp, MatchData 1169signal.c :: Signal 1170sprintf.c :: String#sprintf 1171string.c :: String 1172struct.c :: Struct 1173time.c :: Time 1174 1175defs/known_errors.def :: 例外クラス Errno::* 1176-> known_errors.inc :: 自動生成 1177 1178=== 多言語化 1179 1180encoding.c :: Encoding 1181transcode.c :: Encoding::Converter 1182enc/*.c :: エンコーディングクラス群 1183enc/trans/* :: コードポイント対応表 1184 1185=== gorubyコマンドの実装 1186 1187 goruby.c 1188 golf_prelude.rb : goruby固有のライブラリ 1189 -> golf_prelude.c : 自動生成 1190 1191== Appendix B. 拡張用関数リファレンス 1192 1193C言語からRubyの機能を利用するAPIは以下の通りである. 1194 1195=== 型 1196 1197VALUE :: 1198 1199 Rubyオブジェクトを表現する型.必要に応じてキャストして用いる. 1200 組み込み型を表現するCの型はruby.hに記述してあるRで始まる構造 1201 体である.VALUE型をこれらにキャストするためにRで始まる構造体 1202 名を全て大文字にした名前のマクロが用意されている. 1203 1204=== 変数・定数 1205 1206Qnil :: 1207 1208 定数: nilオブジェクト 1209 1210Qtrue :: 1211 1212 定数: trueオブジェクト(真のデフォルト値) 1213 1214Qfalse :: 1215 1216 定数: falseオブジェクト 1217 1218=== Cデータのカプセル化 1219 1220Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval) :: 1221 1222 Cの任意のポインタをカプセル化したRubyオブジェクトを返す.こ 1223 のポインタがRubyからアクセスされなくなった時,freeで指定した 1224 関数が呼ばれる.また,このポインタの指すデータが他のRubyオブ 1225 ジェクトを指している場合,markに指定する関数でマークする必要 1226 がある. 1227 1228Data_Make_Struct(klass, type, mark, free, sval) :: 1229 1230 type型のメモリをmallocし,変数svalに代入した後,それをカプセ 1231 ル化したデータを返すマクロ. 1232 1233Data_Get_Struct(data, type, sval) :: 1234 1235 dataからtype型のポインタを取り出し変数svalに代入するマクロ. 1236 1237=== 型チェック 1238 1239 RB_TYPE_P(value, type) 1240 TYPE(value) 1241 FIXNUM_P(value) 1242 NIL_P(value) 1243 RB_INTEGER_TYPE_P(value) 1244 RB_FLOAT_TYPE_P(value) 1245 void Check_Type(VALUE value, int type) 1246 SafeStringValue(value) 1247 1248=== 型変換 1249 1250 FIX2INT(value), INT2FIX(i) 1251 FIX2LONG(value), LONG2FIX(l) 1252 NUM2INT(value), INT2NUM(i) 1253 NUM2UINT(value), UINT2NUM(ui) 1254 NUM2LONG(value), LONG2NUM(l) 1255 NUM2ULONG(value), ULONG2NUM(ul) 1256 NUM2LL(value), LL2NUM(ll) 1257 NUM2ULL(value), ULL2NUM(ull) 1258 NUM2OFFT(value), OFFT2NUM(off) 1259 NUM2SIZET(value), SIZET2NUM(size) 1260 NUM2SSIZET(value), SSIZET2NUM(ssize) 1261 rb_integer_pack(value, words, numwords, wordsize, nails, flags), rb_integer_unpack(words, numwords, wordsize, nails, flags) 1262 NUM2DBL(value) 1263 rb_float_new(f) 1264 RSTRING_LEN(str) 1265 RSTRING_PTR(str) 1266 StringValue(value) 1267 StringValuePtr(value) 1268 StringValueCStr(value) 1269 rb_str_new2(s) 1270 1271=== クラス/モジュール定義 1272 1273VALUE rb_define_class(const char *name, VALUE super) :: 1274 1275 superのサブクラスとして新しいRubyクラスを定義する. 1276 1277VALUE rb_define_class_under(VALUE module, const char *name, VALUE super) :: 1278 1279 superのサブクラスとして新しいRubyクラスを定義し,moduleの 1280 定数として定義する. 1281 1282VALUE rb_define_module(const char *name) :: 1283 1284 新しいRubyモジュールを定義する. 1285 1286VALUE rb_define_module_under(VALUE module, const char *name) :: 1287 1288 新しいRubyモジュールを定義し,moduleの定数として定義する. 1289 1290void rb_include_module(VALUE klass, VALUE module) :: 1291 1292 モジュールをインクルードする.classがすでにmoduleをインク 1293 ルードしている時には何もしない(多重インクルードの禁止). 1294 1295void rb_extend_object(VALUE object, VALUE module) :: 1296 1297 オブジェクトをモジュール(で定義されているメソッド)で拡張する. 1298 1299=== 大域変数定義 1300 1301void rb_define_variable(const char *name, VALUE *var) :: 1302 1303 RubyとCとで共有するグローバル変数を定義する.変数名が`$'で 1304 始まらない時には自動的に追加される.nameとしてRubyの識別子 1305 として許されない文字(例えば` ')を含む場合にはRubyプログラ 1306 ムからは見えなくなる. 1307 1308void rb_define_readonly_variable(const char *name, VALUE *var) :: 1309 1310 RubyとCとで共有するread onlyのグローバル変数を定義する. 1311 read onlyであること以外はrb_define_variable()と同じ. 1312 1313void rb_define_virtual_variable(const char *name, VALUE (*getter)(), void (*setter)()) :: 1314 1315 関数によって実現されるRuby変数を定義する.変数が参照された 1316 時にはgetterが,変数に値がセットされた時にはsetterが呼ばれ 1317 る. 1318 1319void rb_define_hooked_variable(const char *name, VALUE *var, VALUE (*getter)(), void (*setter)()) :: 1320 1321 関数によってhookのつけられたグローバル変数を定義する.変数 1322 が参照された時にはgetterが,関数に値がセットされた時には 1323 setterが呼ばれる.getterやsetterに0を指定した時にはhookを 1324 指定しないのと同じ事になる. 1325 1326void rb_global_variable(VALUE *var) :: 1327 1328 マークする必要のあるRubyオブジェクトを含む大域変数を,GC 1329 によって解放されないように保護する. 1330 1331void rb_gc_register_mark_object(VALUE *var) :: 1332 1333 マークする必要のあるRubyオブジェクトを,GCによって解放さ 1334 れないように登録する. 1335 1336=== 定数 1337 1338void rb_define_const(VALUE klass, const char *name, VALUE val) :: 1339 1340 定数を定義する. 1341 1342void rb_define_global_const(const char *name, VALUE val) :: 1343 1344 大域定数を定義する. 1345 1346 rb_define_const(rb_cObject, name, val) 1347 1348 と同じ意味. 1349 1350=== メソッド定義 1351 1352rb_define_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) :: 1353 1354 メソッドを定義する.argcはselfを除く引数の数.argcが-1の時, 1355 関数には引数の数(selfを含まない)を第1引数, 引数の配列を第2 1356 引数とする形式で与えられる(第3引数はself).argcが-2の時, 1357 第1引数がself, 第2引数がargs(argsは引数を含むRubyの配列)と 1358 いう形式で与えられる. 1359 1360rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) :: 1361 1362 privateメソッドを定義する.引数はrb_define_method()と同じ. 1363 1364rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(ANYARGS), int argc) :: 1365 1366 特異メソッドを定義する.引数はrb_define_method()と同じ. 1367 1368rb_check_arity(int argc, int min, int max) :: 1369 1370 引数の数であるargcがmin..maxの範囲に入っているかをチェックします. 1371 もしmaxがUNLIMITED_ARGUMENTSなら,上限はチェックしません. 1372 もしargcが範囲外ならArgumentErrorが発生します. 1373 1374rb_scan_args(int argc, VALUE *argv, const char *fmt, ...) :: 1375 1376 argc, argv形式で与えられた指定されたフォーマットに従って引 1377 数を分解し,続くVALUEへの参照にセットします.このフォーマッ 1378 トは,ABNFで記述すると以下の通りです. 1379 1380 scan-arg-spec := param-arg-spec [option-hash-arg-spec] [block-arg-spec] 1381 1382 param-arg-spec := pre-arg-spec [post-arg-spec] / post-arg-spec / 1383 pre-opt-post-arg-spec 1384 pre-arg-spec := num-of-leading-mandatory-args [num-of-optional-args] 1385 post-arg-spec := sym-for-variable-length-args 1386 [num-of-trailing-mandatory-args] 1387 pre-opt-post-arg-spec := num-of-leading-mandatory-args num-of-optional-args 1388 num-of-trailing-mandatory-args 1389 option-hash-arg-spec := sym-for-option-hash-arg 1390 block-arg-spec := sym-for-block-arg 1391 1392 num-of-leading-mandatory-args := DIGIT ; 先頭に置かれる省略不能な引数の数 1393 num-of-optional-args := DIGIT ; 続いて置かれる省略可能な引数の数 1394 sym-for-variable-length-args := "*" ; 続いて置かれる可変長引数を 1395 ; Rubyの配列で取得するための指定 1396 num-of-trailing-mandatory-args := DIGIT ; 終端に置かれる省略不能な引数の数 1397 sym-for-option-hash-arg := ":" ; オプションハッシュを取得する 1398 ; ための指定; 省略不能な引数の 1399 ; 数よりも多くの引数が指定され, 1400 ; 最後の引数がハッシュ(または 1401 ; #to_hashで変換可能)の場合に 1402 ; 取得される.最後の引数がnilの 1403 ; 場合,可変長引数指定がなく, 1404 ; 省略不能引数の数よりも多くの 1405 ; 引数が指定された場合に取得される 1406 sym-for-block-arg := "&" ; イテレータブロックを取得するための 1407 ; 指定 1408 1409 フォーマットが"12"の場合,引数は最低1つで,3つ(1+2)まで許さ 1410 れるという意味になります.従って,フォーマット文字列に続い 1411 て3つのVALUEへの参照を置く必要があります.それらには取得した 1412 変数がセットされます.変数への参照の代わりにNULLを指定する 1413 こともでき,その場合は取得した引数の値は捨てられます.なお, 1414 省略可能引数が省略された時の変数の値はnil(C言語のレベルでは 1415 Qnil)になります. 1416 1417 返り値は与えられた引数の数です.オプションハッシュおよびイ 1418 テレータブロックは数えません. 1419 1420int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values) :: 1421 1422 キーワードで指定された値をtableにしたがって取り出します. 1423 tableの最初のrequired個のIDは必須キーワードを表し,続く 1424 optional (optionalが負の場合は-optional-1) 個のIDは省略可能 1425 キーワードです.必須キーワードがkeyword_hash中にない場合, 1426 "missing keyword"ArgumentErrorが発生します.省略可能キーワー 1427 ドがない場合は,values中の対応する要素にはQundefがセットされ 1428 ます.keyword_hashに使用されない要素がある場合は,optionalが 1429 負なら無視されますが,そうでなければ"unknown keyword" 1430 ArgumentErrorが発生します. 1431 1432VALUE rb_extract_keywords(VALUE *original_hash) :: 1433 1434 original_hashで参照されるHashオブジェクトから,Symbolである 1435 キーとその値を新しいHashに取り出します.original_hashの指す 1436 先には,元のHashがSymbol以外のキーを含んでいた場合はそれらが 1437 コピーされた別の新しいHash,そうでなければ0が保存されます. 1438 1439=== Rubyメソッド呼び出し 1440 1441VALUE rb_funcall(VALUE recv, ID mid, int narg, ...) :: 1442 1443 メソッド呼び出し.文字列からmidを得るためにはrb_intern()を 1444 使う. 1445 private/protectedなメソッドでも呼び出せる. 1446 1447VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv) :: 1448VALUE rb_funcallv(VALUE recv, ID mid, int argc, VALUE *argv) :: 1449 1450 メソッド呼び出し.引数をargc, argv形式で渡す. 1451 private/protectedなメソッドでも呼び出せる. 1452 1453VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, VALUE *argv) :: 1454 1455 メソッド呼び出し. 1456 publicなメソッドしか呼べない. 1457 1458VALUE rb_eval_string(const char *str) :: 1459 1460 文字列をRubyスクリプトとしてコンパイル・実行する. 1461 1462ID rb_intern(const char *name) :: 1463 1464 文字列に対応するIDを返す. 1465 1466char *rb_id2name(ID id) :: 1467 1468 IDに対応する文字列を返す(デバッグ用). 1469 1470char *rb_class2name(VALUE klass) :: 1471 1472 クラスの名前を返す(デバッグ用).クラスが名前を持たない時に 1473 は, 祖先を遡って名前を持つクラスの名前を返す. 1474 1475int rb_respond_to(VALUE obj, ID id) :: 1476 1477 objがidで示されるメソッドを持つかどうかを返す. 1478 1479=== インスタンス変数 1480 1481VALUE rb_iv_get(VALUE obj, const char *name) :: 1482 1483 objのインスタンス変数の値を得る.`@'で始まらないインスタン 1484 ス変数は Rubyプログラムからアクセスできない「隠れた」イン 1485 スタンス変数になる.定数は大文字の名前を持つクラス(または 1486 モジュール)のインスタンス変数として実装されている. 1487 1488VALUE rb_iv_set(VALUE obj, const char *name, VALUE val) :: 1489 1490 objのインスタンス変数をvalにセットする. 1491 1492=== 制御構造 1493 1494VALUE rb_block_call(VALUE obj, ID mid, int argc, VALUE * argv, VALUE (*func) (ANYARGS), VALUE data2) :: 1495 1496 funcをブロックとして設定し,objをレシーバ,argcとargvを引数 1497 としてmidメソッドを呼び出す.funcは第一引数にyieldされた値, 1498 第二引数にdata2を受け取る.複数の値がyieldされた場合(Cでは 1499 rb_yield_values()とrb_yield_values2(), rb_yield_splat()), 1500 data2はArrayとしてパックされている.第三, 第四引数のargcと 1501 argvによってyieldされた値を取り出すことができる. 1502 1503\[OBSOLETE] VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2) :: 1504 1505 func2をブロックとして設定し, func1をイテレータとして呼ぶ. 1506 func1には arg1が引数として渡され, func2には第1引数にイテレー 1507 タから与えられた値, 第2引数にarg2が渡される. 1508 1509 1.9でrb_iterateを使う場合は, func1の中でRubyレベルのメソッド 1510 を呼び出さなければならない. 1511 1.9でobsoleteとなった. 代わりにrb_block_callが用意された. 1512 1513VALUE rb_yield(VALUE val) :: 1514 1515 valを値としてイテレータブロックを呼び出す. 1516 1517VALUE rb_rescue(VALUE (*func1)(ANYARGS), VALUE arg1, VALUE (*func2)(ANYARGS), VALUE arg2) :: 1518 1519 関数func1をarg1を引数に呼び出す.func1の実行中に例外が発生 1520 した時には func2をarg2を第一引数, 発生した例外オブジェクト 1521 を第二引数として呼ぶ.戻り値は例外が発生しなかった時はfunc1 1522 の戻り値, 例外が発生した時にはfunc2の戻り値である. 1523 1524VALUE rb_ensure(VALUE (*func1)(ANYARGS), VALUE arg1, VALUE (*func2)(ANYARGS), VALUE arg2) :: 1525 1526 関数func1をarg1を引数として実行し, 実行終了後(たとえ例外が 1527 発生しても) func2をarg2を引数として実行する.戻り値はfunc1 1528 の戻り値である(例外が発生した時は戻らない). 1529 1530VALUE rb_protect(VALUE (*func) (VALUE), VALUE arg, int *state) :: 1531 1532 関数funcをargを引数として実行し, 例外が発生しなければその戻 1533 り値を返す.例外が発生した場合は, *stateに非0をセットして 1534 Qnilを返す. 1535 rb_jump_tag()を呼ばずに捕捉した例外を無視する場合には, 1536 rb_set_errinfo(Qnil)でエラー情報をクリアしなければならない. 1537 1538void rb_jump_tag(int state) :: 1539 1540 rb_protect()やrb_eval_string_protect()で捕捉された例外を再 1541 送する.stateはそれらの関数から返された値でなければならない. 1542 この関数は直接の呼び出し元に戻らない. 1543 1544void rb_iter_break() :: 1545 1546 現在の最も内側のブロックを終了する.この関数は直接の呼び出 1547 し元に戻らない. 1548 1549void rb_iter_break_value(VALUE value) :: 1550 1551 現在の最も内側のブロックをvalueで終了する.ブロックは引数で 1552 与えられたvalueを返す.この関数は直接の呼び出し元に戻らない. 1553 1554=== 例外・エラー 1555 1556void rb_warning(const char *fmt, ...) :: 1557 1558 rb_verbose時に標準エラー出力に警告情報を表示する.引数は 1559 printf()と同じ. 1560 1561void rb_raise(rb_eRuntimeError, const char *fmt, ...) :: 1562 1563 RuntimeError例外を発生させる.引数はprintf()と同じ. 1564 1565void rb_raise(VALUE exception, const char *fmt, ...) :: 1566 1567 exceptionで指定した例外を発生させる.fmt以下の引数は 1568 printf()と同じ. 1569 1570void rb_fatal(const char *fmt, ...) :: 1571 1572 致命的例外を発生させる.通常の例外処理は行なわれず, インター 1573 プリタが終了する(ただしensureで指定されたコードは終了前に 1574 実行される). 1575 1576void rb_bug(const char *fmt, ...) :: 1577 1578 インタープリタなどプログラムのバグでしか発生するはずのない 1579 状況の時呼ぶ.インタープリタはコアダンプし直ちに終了する. 1580 例外処理は一切行なわれない. 1581 1582注意: "%"PRIsVALUEがObject#to_s('+'フラグが指定されていると 1583きはObject#inspect)を使ったVALUEの出力に利用できる.これは 1584"%i"と衝突するため,整数には"%d"を使用すること. 1585 1586=== Rubyの初期化・実行 1587 1588Rubyをアプリケーションに埋め込む場合には以下のインタフェース 1589を使う.通常の拡張ライブラリには必要ない. 1590 1591void ruby_init() :: 1592 1593 Rubyインタプリタの初期化を行なう. 1594 1595void *ruby_options(int argc, char **argv) :: 1596 1597 Rubyインタプリタのコマンドライン引数の処理を行ない, 1598 Rubyのソースコードをコンパイルする. 1599 コンパイルされたソースへのポインタ,もしくは特殊値を返す. 1600 1601int ruby_run_node(void *n) :: 1602 1603 コンパイルされたコードを実行する. 1604 実行に成功した場合はEXIT_SUCCESSを,エラーが起こったときはそれ以外を返す. 1605 1606void ruby_script(char *name) :: 1607 1608 Rubyのスクリプト名($0)を設定する. 1609 1610=== インタプリタのイベントのフック 1611 1612void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data) :: 1613 1614 指定されたインタプリタのイベントに対するフック関数を追加します. 1615 eventsは以下の値のorでなければなりません: 1616 1617 RUBY_EVENT_LINE 1618 RUBY_EVENT_CLASS 1619 RUBY_EVENT_END 1620 RUBY_EVENT_CALL 1621 RUBY_EVENT_RETURN 1622 RUBY_EVENT_C_CALL 1623 RUBY_EVENT_C_RETURN 1624 RUBY_EVENT_RAISE 1625 RUBY_EVENT_ALL 1626 1627 rb_event_hook_func_tの定義は以下の通りです: 1628 1629 typedef void (*rb_event_hook_func_t)(rb_event_t event, VALUE data, 1630 VALUE self, ID id, VALUE klass) 1631 1632 rb_add_event_hook() の第3引数 data は,フック関数の第2引数と 1633 して渡されます.これは1.8では現在のNODEへのポインタでした.以 1634 下の RB_EVENT_HOOKS_HAVE_CALLBACK_DATA も参照してください. 1635 1636int rb_remove_event_hook(rb_event_hook_func_t func) :: 1637 1638 指定されたフック関数を削除します. 1639 1640=== メモリ使用量 1641 1642void rb_gc_adjust_memory_usage(ssize_t diff) :: 1643 1644 登録された外部のメモリ使用量を調整します.この関数で外部のライブラリが 1645 どのくらいメモリを使っているのかをGCに伝えることができます.正のdiffで 1646 この関数を呼び出すとメモリ使用量の増加を意味します.新しいメモリブロッ 1647 クが確保されたり,ブロックがより大きなサイズで再割り当てされたりした場 1648 合などです.負のdiffでこの関数を呼び出すとメモリ使用量の減少を意味しま 1649 す.メモリブロックが解放されたり,メモリブロックがより小さいサイズで再 1650 確保されたりした場合などです.この関数はGCを引き起こすかもしれません. 1651 1652=== 互換性のためのマクロ 1653 1654APIの互換性をチェックするために以下のマクロがデフォルトで定義されています. 1655 1656NORETURN_STYLE_NEW :: 1657 1658 NORETURN マクロが関数型マクロとして定義されていることを意味する. 1659 1660HAVE_RB_DEFINE_ALLOC_FUNC :: 1661 1662 rb_define_alloc_func() 関数が提供されていること,つまり 1663 allocation framework が使われることを意味する. 1664 have_func("rb_define_alloc_func", "ruby.h") 1665 の結果と同じ. 1666 1667HAVE_RB_REG_NEW_STR :: 1668 1669 StringオブジェクトからRegexpオブジェクトを作る 1670 rb_reg_new_str() 関数が提供されていることを意味する. 1671 have_func("rb_reg_new_str", "ruby.h"). 1672 の結果と同じ. 1673 1674HAVE_RB_IO_T :: 1675 1676 rb_io_t 型が提供されていることを意味する. 1677 1678USE_SYMBOL_AS_METHOD_NAME :: 1679 1680 メソッド名を返すメソッド,Module#methods, \#singleton_methods 1681 などがSymbolを返すことを意味する. 1682 1683HAVE_RUBY_*_H :: 1684 1685 ruby.h で定義されている.対応するヘッダが提供されていること 1686 を意味する.たとえば,HAVE_RUBY_ST_H が定義されている場合は 1687 単なる st.h ではなく ruby/st.h を使用する. 1688 1689RB_EVENT_HOOKS_HAVE_CALLBACK_DATA :: 1690 1691 rb_add_event_hook() がフック関数に渡す data を第3引数として 1692 受け取ることを意味する. 1693 1694== Appendix C. extconf.rbで使える関数たち 1695 1696extconf.rbの中では利用可能なコンパイル条件チェックの関数は以 1697下の通りである. 1698 1699have_macro(macro, headers) :: 1700 1701 ヘッダファイルheaderをインクルードしてマクロmacroが定義さ 1702 れているかどうかチェックする.マクロが定義されている時true 1703 を返す. 1704 1705have_library(lib, func) :: 1706 1707 関数funcを定義しているライブラリlibの存在をチェックする. 1708 チェックに成功すると,-llibを$libsに追加し,trueを返す. 1709 1710find_library(lib, func, path...) :: 1711 1712 関数funcを定義しているライブラリlibの存在を -Lpath を追加 1713 しながらチェックする.チェックに成功すると,-llibを$libsに 1714 追加し,trueを返す. 1715 1716have_func(func, header) :: 1717 1718 ヘッダファイルheaderをインクルードして関数funcの存在をチェ 1719 ックする.funcが標準ではリンクされないライブラリ内のもので 1720 ある時には先にhave_libraryでそのライブラリをチェックしてお 1721 く事.チェックに成功すると,プリプロセッサマクロ 1722 `HAVE_{FUNC}` を定義し,trueを返す. 1723 1724have_var(var, header) :: 1725 1726 ヘッダファイルheaderをインクルードして変数varの存在をチェッ 1727 クする.varが標準ではリンクされないライブラリ内のものであ 1728 る時には先にhave_libraryでそのライブラリをチェックしておく 1729 事.チェックに成功すると,プリプロセッサマクロ 1730 `HAVE_{VAR}` を定義し,trueを返す. 1731 1732have_header(header) :: 1733 1734 ヘッダファイルの存在をチェックする.チェックに成功すると, 1735 プリプロセッサマクロ `HAVE_{HEADER_H}` を定義し,trueを返す. 1736 (スラッシュやドットはアンダースコアに置換される) 1737 1738find_header(header, path...) :: 1739 1740 ヘッダファイルheaderの存在を -Ipath を追加しながらチェック 1741 する.チェックに成功すると,プリプロセッサマクロ 1742 `HAVE_{HEADER_H}` を定義し,trueを返す. 1743 (スラッシュやドットはアンダースコアに置換される) 1744 1745have_struct_member(type, member[, header[, opt]]) :: 1746 1747 ヘッダファイルheaderをインクルードして型typeが定義され, 1748 なおかつメンバmemberが存在するかをチェックする.チェックに 1749 成功すると,プリプロセッサマクロ `HAVE_{TYPE}_{MEMBER}` を 1750 定義し,trueを返す. 1751 1752have_type(type, header, opt) :: 1753 1754 ヘッダファイルheaderをインクルードして型typeが存在するかを 1755 チェックする.チェックに成功すると,プリプロセッサマクロ 1756 `HAVE_TYPE_{TYPE}` を定義し,trueを返す. 1757 1758check_sizeof(type, header) :: 1759 1760 ヘッダファイルheaderをインクルードして型typeのchar単位サイ 1761 ズを調べる.チェックに成功すると,プリプロセッサマクロ 1762 `SIZEOF_{TYPE}` を定義し,そのサイズを返す.定義されていな 1763 いときはnilを返す. 1764 1765create_makefile(target[, target_prefix]) :: 1766 1767 拡張ライブラリ用のMakefileを生成する.この関数を呼ばなけれ 1768 ばそのライブラリはコンパイルされない.targetはモジュール名 1769 を表す. 1770 1771find_executable(command, path) :: 1772 1773 コマンドcommandをFile::PATH_SEPARATORで区切られたパス名の 1774 リストpathから探す.pathがnilまたは省略された場合は,環境 1775 変数PATHの値を使用する.実行可能なコマンドが見つかった場合 1776 はパスを含むファイル名,見つからなかった場合はnilを返す. 1777 1778with_config(withval[, default=nil]) :: 1779 1780 コマンドライン上の--with-<withval>で指定されたオプション値 1781 を得る. 1782 1783enable_config(config, *defaults) :: 1784disable_config(config, *defaults) :: 1785 1786 コマンドライン上の--enable-<config>または 1787 --disable-<config>で指定された真偽値を得る. 1788 --enable-<config>が指定されていた場合はtrue, 1789 --disable-<config>が指定されていた場合はfalseを返す. 1790 どちらも指定されていない場合は,ブロックつきで呼び出されて 1791 いる場合は*defaultsをyieldした結果,ブロックなしなら 1792 \*defaultsを返す. 1793 1794dir_config(target[, default_dir]) :: 1795dir_config(target[, default_include, default_lib]) :: 1796 1797 コマンドライン上の--with-<target>-dir, --with-<target>-include, 1798 --with-<target>-libのいずれかで指定されるディレクトリを 1799 $CFLAGS や $LDFLAGS に追加する.--with-<target>-dir=/pathは 1800 --with-<target>-include=/path/include --with-<target>-lib=/path/lib 1801 と等価である.追加された include ディレクトリと lib ディレ 1802 クトリの配列を返す. ([include_dir, lib_dir]) 1803 1804pkg_config(pkg, option=nil) :: 1805 1806 pkg-configコマンドからパッケージpkgの情報を [cflags, ldflags, libs] 1807 の配列として得る.$CFLAGS, $LDFLAGS, $libs にはそれぞれの値が 1808 追加される. 1809 1810 pkg-configの実際のコマンドは,以下の順で試される. 1811 1812 1. コマンドラインで--with-{pkg}-config={command}オプションが 1813 指定された場合: {command} {option} 1814 2. {pkg}-config {option} 1815 3. pkg-config {option} {pkg} 1816 1817 optionが指定された場合は,上記の配列の代わりにそのオプションを 1818 指定して得られた出力をstripしたものを返す. 1819 1820== Appendix D. 世代別GC 1821 1822Ruby 2.1から世代別GCに対応しました.我々はこれをRGenGCと呼んでいます. 1823RGenGCは,過去の拡張ライブラリに(ほぼ)互換性を保つように開発されている 1824ため,拡張ライブラリ側の対応はほぼ不要です. 1825 1826ただし,対応をすることで性能を向上することができる可能性があります.もし 1827拡張ライブラリに高い性能が必要である場合は対応を検討して下さい. 1828 1829とくにRARRAY_PTR()/RHASH_TBL()のようなマクロを用いてポインタに直接アクセ 1830スするようなコードは書かないようにして下さい.代わりに,rb_ary_aref(), 1831rb_ary_store() などの,適切な API 関数を利用するようにして下さい. 1832 1833そのほか,対応についての詳細は extension.rdoc の「Appendix D. Generational 1834GC」を参照して下さい. 1835 1836:enddoc: Local variables: 1837:enddoc: fill-column: 60 1838:enddoc: end: 1839