mrubyであるクラスに特定の名前のメソッドが存在しているか調べる方法
次のPictRubyで以下のような対話型のプログラムが簡単に書けるようになる。
スクリプトはこんな感じ。(書き方は模索中、そのうち変わるかも)
def chat(input) @num ||= 0 case input when "name", "Name" "My name is Rubo" when "Rubo" "Yes, my load." when "help", "Help" <<EOF Echo your message name: teach my name halt: stop this program EOF when "halt", "Halt" aaaa else @num += 1 "#{@num}: #{input}" end end
今までのプログラムと同居するために、スクリプトにchatとmainどちらの関数が定義されているかを調べて、生成するViewControllerを切り替える必要が出てきた。
いろいろと試行錯誤の結果以下のようになった。
+ (id) NewWithScriptName:(NSString*)scriptPath { mrb_state* mrb = [self InitMrb:scriptPath]; // ScriptController or ChatViewController mrb_sym mid = mrb_intern_cstr(mrb, "chat"); struct RProc* m = mrb_method_search_vm(mrb, &mrb->object_class, mid); if (m) { return [[ChatViewController alloc] init:scriptPath mrb:mrb]; } else { return [[ScriptController alloc] init:scriptPath mrb:mrb]; } }
mrb_intern_cstr
とmrb_method_search_vm
の組み合わせで調べられる(&classなことに注意)。最初、
struct RProc* m = mrb_method_search_vm(mrb, &mrb->kernel_class, mid);
ってやっても全然見つからなくて、そうかグローバル関数(本当はそんなものRubyにはないのだろうけど)はKernelじゃなくてObjectに所属するのか、ってなった。mrb_funcallの時は中でうまくmessod_missingしてくれているのかな?