From: masahiko yamada/Daiwasbcm Date: 2001-02-21T12:27:05+09:00 Subject: [ruby-list:28119] C からのコールバックでエラー はじめまして、山田と申します。 初の書き込みをさせていただきます。 C向けに書かれたネットワークデータ取得APIをRubyから使用するため、拡張 モジュールを作成してみたところ分からないことにぶつかりました。 ruby 1.6.2 (2000-12-25) [i586-mswin32] WinNT 4.0 そのAPIは、int (*)(void*, unsigned int) などという型のコールバック関 数を登録しておき、LANからデータが到達したときにクライアントにそれを処 理させる機会を与えてくれるものです。 コールバックをRubyのブロックとして表現できると便利だと思い、下記のよ うな拡張モジュールを作成しました(VC++ 6.0)。 ------------------------------------------------------------ VALUE mModule; const ID callID = rb_intern("call"); const ID disableID = rb_intern("disable"); const ID enableID = rb_intern("enable"); VALUE block; //Proc //ライブラリからコールバックされる関数 int CallBack(void* data, unsigned int len) { rb_funcall(rb_mGC, disableID, 0); //なぜ必要? if ( data && len ) { VALUE str = rb_str_new((const char*)data, len); rb_funcall(block, callID, 1, str); } else { rb_funcall(block, callID, 1, Qnil); } rb_funcall(rb_mGC, enableID, 0); //なぜ必要? return 0; } VALUE getService_m(VALUE m, VALUE blk) { block = blk; rb_global_variable(&block); //? ライブラリへの登録関数(&CallBack); return Qnil; } void Init_****() { mModule = rb_define_module("MyModule"); rb_define_module_function(mModule, "getService_m", getService_m, 1) } ------------------------------------------------------------ Rubyからは、 class MyClass include MyModule def getService(&b) MyModule.getService_m(b) end end MyClass.new.getService { |x| puts x } というように使っています。 ここで、‘なぜ必要?’と書いた個所をコメントアウトすると数十件のデー タを処理した時点で、 [BUG] rb_gc_mark(); unknown data type 0x0(0x241f570) non object などと言って落ちてしまいます。コメントをはずしてやると、しばらく順調に 動いているのですが数千件まで到達するとやはり同じエラーで落ちてしまいま す。 Cからのコールバックにブロックを使用する場合に一般的に注意すべき点が あって私がそれをはずしているのでしょうか? 教えていただけるとありがたいです。長文失礼しました。