Class 型の構造体は、とうぜん、メソッドの定義も持っている。だけど、取り出すにはちょっと工夫が必要。Class 型の定義を見てみてくれ。メソッドの定義である、objc_method_list 型の methodLists というフィールドがあるんだけど、、、
/usr/include/objc/objc-class.h
struct objc_class {
...
struct objc_method_list **methodLists;
...
};
ポインタのポインタになっていることからも想像できるように、こいつはメソッドのリストのリストだ。つまり、クラスのメソッドの定義は、複数のメソッドリストからできてるんだ。なんで、いくつかに分かれているのか?実行結果から推測すると、カテゴリごとに分かれているようだ(明確な記述がないから、あくまで推測)。
アクセスするには、専用の関数が用意されている(ポインタのポインタをインクリメントしてやっても、うまくいかなかった)。
/usr/include/objc/objc-class.h
OBJC_EXPORT struct objc_method_list *class_nextMethodList(Class, void **);
これを使えば、メソッドのリストのリストにアクセスできて、メソッドのリストを取り出すことができる。使用例は、こんな感じ。
showMethods() (sample)
void* iterator = 0;
struct objc_method_list* mlist;
while(mlist = class_nextMethodList(klass, &iterator)) {
Method method = mlist->method_list;
...
}
}
これで、メソッドのリストである、Method 型の method_list を取り出すことができるんだ。
上のようにして、メソッドのリストを得たら、そこからメソッドのリストを取り出す。Method の定義は、
/usr/include/objc/objc-class.h
typedef struct objc_method *Method;
であって、じゃあ struct objc_method の定義はどうか、っていうと、
/usr/include/objc/objc-class.h
struct objc_method_list {
struct objc_method_list *obsolete;
int method_count;
#ifdef __alpha__
int space;
#endif
struct objc_method {
SEL method_name;
char *method_types;
IMP method_imp;
} method_list[1]; /* variable length structure */
};
こうだ。method_count でメソッドの数を調べて、その数だけ method_list がある。そこから method_name とか method_types とかが得られるんだ。
method_name の型である SEL 型の定義は、/usr/include/objc/objc.h にある。
/usr/include/objc/objc.h
typedef struct objc_selector *SEL;
じゃあ、struct objc_selector の定義は、、、ないぞ!?見つからないー。公開してないのか?てなわけで、他のドキュメントを探ると、SEL は char へのポインタで、その先は C の文字列になってるらしい(『ところで、セレクタってなんなのさ?』の項を参照)。
というわけで、クラスから、メソッドの名前と型を取り出して表示する、サンプルコード。
showMethods() (sample)
void showMethods(Class klass)
{
void* iterator = 0;
struct objc_method_list* mlist;
int i;
printf("class: %s?", klass->name);
while(mlist = class_nextMethodList(klass, &iterator)) {
Method method = mlist->method_list;
printf("method count: %d?", mlist->method_count);
for(i = 0; i < mlist->method_count; i++) {
printf(" method_name: %s?", (char*)method->method_name);
printf(" method_types: %s?", method->method_types);
method++;
}
}
}
これでメソッドの名前は分かる。次の問題は、メソッドの型だな。