最初の敗北: Object 編
Objective-C入門を一読して、小さな Objective-C のソースコードを書いてみた。以下の通り:
#import <objc/Object.h>
#import <stdio.h>
@interface Point : Object
{
int x;
}
-(id) setX :(int)x;
-(int) getX;
@end
@implementation Point
-(id) setX :(int)x
{
self->x = x;
return self;
}
-(int) getX {
return x;
}
@end
int main(void)
{
id point = [Point alloc];
[point setX: 10];
printf("Point X is %d\n.", [point getX]);
return 0;
}
このコードを前エントリーの Makefile (必要部分だけ抜粋) を使ってコンパイル。
#
# Makefile for hello
#
TARGET = hello
OBJC = gcc
OBJCFLAGS = -W -Wall
LIB = -lobjc
all: $(TARGET)
$(TARGET): main.o
$(OBJC) $(OBJCFLAGS) $^ $(LIB) -o $@
%.o: %.m
$(OBJC) $(OBJCFLAGS) -c $< -o $@
実行結果は次の通り。Warning は出ているけど、エラーは出てない。
$ LANG=C make -k gcc -g -W -Wall -c main.m -o main.o main.m: In function '-[Point setX:]': main.m:15:3: warning: local declaration of 'x' hides instance variable [enabled by default] main.m: In function 'main': main.m:25:3: warning: 'Point' may not respond to '+alloc' [enabled by default] main.m:25:3: warning: (Messages without a matching method signature [enabled by default] main.m:25:3: warning: will be assumed to return 'id' and accept [enabled by default] main.m:25:3: warning: '...' as arguments.) [enabled by default] gcc -g -W -Wall main.o -lobjc -o hello Compilation finished at Wed Apr 3 12:15:28
で、これを実行すると失敗。
$ ./hello Segmentation fault (コアダンプ)
次のトライ: NSObject 編
色々試して行き詰まったので、Ubuntu LinuxでObjective-C - Tomute’s Notes の記事を参考に NSObject を使う方向に方針転換。
インストール
NSObject を使うためのインストールを実行
$ sudo apt-get install libgnustep-base-dev $ sudo apt-get install gnustep $ sudo apt-get install gnustep-devel
Makefile の編集
OBJCFLAGS
と LIBS
に NSObject 用の設定を追記。面倒なので全部コピペしちゃう。
#
# Makefile for hello
#
TARGET = hello
OBJC = gcc
OBJCFLAGS = -I/usr/include/GNUstep -fconstant-string-class=NSConstantString -W -Wall
LIB = -lobjc -lgnustep-base
all: $(TARGET)
$(TARGET): main.o
$(OBJC) $(OBJCFLAGS) $^ $(LIB) -o $@
%.o: %.m
$(OBJC) $(OBJCFLAGS) -c $< -o $@
#
# clean
#
RM = rm -f
clean:
$(RM) *~
$(RM) *.o
distclean: clean
$(RM) $(TARGET)
ソースコードの編集
こちらの変更は小さい。#import <objc/Object.h>
を #import <Foundation/NSObject.h>
に変えて、スーパークラス Object
を NSObject
に変更する。
これでコンパイルが通るはず... と思ったら、setX
メソッドでエラー。
self->x = x;
このコードがインスタンス変数 x
を遮蔽しているという。Object を使った時にも同じ文言が出たけど、その時は「エラー」じゃなくて「警告」だったのに... 何故?
とりあえず、ベタな修正をかけて、ハイ完成。
#import <Foundation/NSObject.h> #import <stdio.h> @interface Point : NSObject { int x; } -(id) setX :(int)x_; -(int) getX; @end @implementation Point -(id) setX :(int)x_ { x = x_; return self; } -(int) getX { return x; } @end int main(void) { id point = [Point alloc]; [point setX: 10]; printf("Point X is %d\n.", [point getX]); return 0; }
これでコンパイルして実行すると、めでたし Objective-C のプログラムが実行できた。
$ ./hello Point X is 10
あとがき
もしかして、Object を使ってた時も self
がいけなかったんじゃないかと、NSObject と同じ様にコードを修正してみたものの、再び Segmentation fault になった。何故? 何が足りないの?
あと、self は使えないの? 色々悶々と悩みながら Objective-C のプログラミングを勉強中。ああ、なんか釈然としない。
No comments:
Post a Comment