日記帳

日記です。

Mac OS X と Objective-C 2.0 の Object クラス

Foundation Framework の NSObject じゃなくて Object クラスの話です.

久しぶりに昔書いた Objecive-C のコードを Mac OS X 上でいじってたら軒並み動かなかった.よくわからないので適当にテストコードを書いてみる.

#include <stdio.h>
#include <objc/Object.h>

@interface Hello : Object {
	char *message;
}
+ newWithMessage:(const char *)message;
- initWithMessage:(const char *)message;
-(void)printMessage;
@end

@implementation Hello
+ newWithMessage:(const char *)aMessage {
	return [[self alloc] initWithMessage:aMessage];
}
- initWithMessage:(const char *)aMessage {
	self = [super init];
	message = aMessage;
	return self;
}
-(void)printMessage {
	printf("%s\n", message);
}
@end

int main(int argc, char* argv[]) {
	id hello = [Hello newWithMessage:"Hello, Objective-C World!!"];
	[hello printMessage];
	return 0;
}

こんな感じの hello.m を書いて以下のようにコンパイル

$ gcc -o hello hello.m  -lobjc
hello.m: In function ‘+[Hello newWithMessage:]’:
hello.m:21: warning: ‘Hello’ may not respond to ‘+alloc’
hello.m:21: warning: (Messages without a matching method signature
hello.m:21: warning: will be assumed to return ‘id’ and accept
hello.m:21: warning: ‘...’ as arguments.)
hello.m: In function ‘-[Hello initWithMessage:]’:
hello.m:25: warning: ‘Object’ may not respond to ‘-init’
hello.m:26: warning: assignment discards qualifiers from pointer target type

Object クラスにクラスメソッド alloc やメソッド init がないと警告がでる. 実行ファイルはできたので実行してみたら以下のようなエラーが出て動かない.

$ ./hello 
objc[73654]: Hello: Does not recognize selector forward::
Illegal instruction

alloc なかったらどうやってオブジェクト作ったらいいんだろう?

とりあえず /usr/include/objc/Object.h を見てみる.

#if __OBJC2__

@interface Object
{
	Class isa;	/* A pointer to the instance's class structure */
}

+class;
-(BOOL) isEqual:anObject;

@end

#else

@interface Object
{
	Class isa;	/* A pointer to the instance's class structure */
}

/* Initializing classes and instances */

+ initialize;
- init;

/* Creating, copying, and freeing instances */

+ new;
+ free;
- free;
+ alloc;
<略>
@end

どうやら __OBJC2__ マクロが定義されているとメソッドが軒並みなくなるらしい… Objective-C 2.0 で GC が導入された関係かな?

試しに __OBJC2__ を未定義にしてコンパイルして実行してみる.

$ gcc -o hello hello.m -U__OBJC2__ -lobjc
$ ./hello 
objc[74015]: 
Illegal instruction

コンパイル時に警告は出なくなったが実行時エラーが起きるのはかわらない. ヘッダだけをごまかしても同じライブラリを同じようにリンクしているなら当然の結果か…

Objective-C 2.0 じゃない状態(1.0?)でコンパイルするにはどうすればいいのかしら?