yebisu:objc hirokuma$ gcc -o tst 1.m#import <stdio.h>@interface Hell+ (void)print;
@end@implementation Hell+ (void)print
{printf("Hell\n");}@endint main(void){[Hell print];return 0;
}
Undefined symbols for architecture x86_64:
"__objc_empty_cache", referenced from:
_OBJC_METACLASS_$_Hell in ccJImdLx.o
_OBJC_CLASS_$_Hell in ccJImdLx.o
"__objc_empty_vtable", referenced from:
_OBJC_METACLASS_$_Hell in ccJImdLx.o
_OBJC_CLASS_$_Hell in ccJImdLx.o
"_objc_msgSend", referenced from:
_main in ccJImdLx.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
リンクエラーだ。
オブジェクトだけ作ってみよう。
yebisu:objc hirokuma$ gcc -c 1.m
yebisu:objc hirokuma$ ls
1.m 1.o
yebisu:objc hirokuma$ nm 1.o
0000000000000000 t +[Hell print]
00000000000001c0 s +[Hell print].eh
00000000000001a8 s EH_frame0
000000000000006f s L_.str
0000000000000082 s L_OBJC_CLASS_NAME_0
0000000000000074 s L_OBJC_METH_VAR_NAME_0
000000000000007a s L_OBJC_METH_VAR_TYPE_0
0000000000000170 S _OBJC_CLASS_$_Hell
0000000000000148 S _OBJC_METACLASS_$_Hell
U __objc_empty_cache
U __objc_empty_vtable
0000000000000030 T _main
00000000000001f0 S _main.eh
U _objc_msgSend
U _puts
0000000000000098 s l_OBJC_$_CLASS_METHODS_Hell
0000000000000100 s l_OBJC_CLASS_RO_$_Hell
00000000000000b8 s l_OBJC_METACLASS_RO_$_Hell
えーっと・・・、「U」が外部を参照しているとかだっけ。
putsは、引数無しのprintf()だから置き換えられてるのかな。
そこはgccがlibcをリンクするから解決するけど、objc部分はライブラリを指定せんといかんと言うことか。
うーん、Objective-Cのライブラリ名ってなんだろう・・・。
yebisu:objc hirokuma$ gcc -o tst 1.m -lobjc
yebisu:objc hirokuma$ ./tst
Hell
あ、通った。
yebisu:objc hirokuma$ nm tst
0000000100000e70 t +[Hell print]
0000000100001170 S _NXArgc
0000000100001178 S _NXArgv
0000000100001148 S _OBJC_CLASS_$_Hell
0000000100001120 S _OBJC_METACLASS_$_Hell
0000000100001188 S ___progname
0000000100000000 T __mh_execute_header
U __objc_empty_cache
U __objc_empty_vtable
0000000100001180 S _environ
U _exit
0000000100000ea0 T _main
U _objc_msgSend
U _puts
0000000100001000 s _pvars
U dyld_stub_binder
0000000100000e30 T start
よくわからんが、「Objective-Cはメソッド呼出じゃなくてメッセージ送信」というのだが、動作としてそう作ってるんだな。
もちろん、print()をC風にすると関数呼び出しになる(と思う)。
yebisu:objc hirokuma$ nm tst#import <stdio.h>void print()
{printf("Hell\n");}int main(void){print();return 0;
}
0000000100001050 S _NXArgc
0000000100001058 S _NXArgv
0000000100001068 S ___progname
0000000100000000 T __mh_execute_header
0000000100001060 S _environ
U _exit
0000000100000ed0 T _main
0000000100000eb0 T _print
U _puts
0000000100001000 s _pvars
U dyld_stub_binder
0000000100000e70 T start
拡張子を.mmにすると、C++もいけるらしい。
yebisu:objc hirokuma$ nm tst#import <stdio.h>class Hell {
public:
static void print();};void Hell::print()
{printf("Hell\n");
}int main(void){Hell::print();return 0;
}
0000000100001050 S _NXArgc
0000000100001058 S _NXArgv
0000000100000eb0 T __ZN4Hell5printEv
0000000100001068 S ___progname
0000000100000000 T __mh_execute_header
0000000100001060 S _environ
U _exit
0000000100000ed0 T _main
U _puts
0000000100001000 s _pvars
U dyld_stub_binder
0000000100000e70 T start
まあ、違いはprint()のマングリングした名前くらいか。
0 件のコメント:
コメントを投稿
コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。
注: コメントを投稿できるのは、このブログのメンバーだけです。