Thursday, January 27, 2011

A peek into the Objective-C "runtime"

I'm playing with Cocoa today. I ran across a post (here), reminding me that all our fancy "messages" get changed by the Objective-C "runtime." The real call is objc_msgSend and you can do that yourself if you want:


// gcc test.m -o test -framework Foundation
#import <Foundation/Foundation.h>

@interface MyClass:NSObject {}
-(NSString *) speak:(int) n;
@end

@implementation MyClass
-(NSString *) speak:(int) n {
int i;
NSMutableArray *mA;
mA = [NSMutableArray arrayWithCapacity:n];
for (i=0; i<n; i++) {
[mA addObject:@"woof"];
}
return [mA componentsJoinedByString:@"-"];
}
@end

int main(){
NSAutoreleasePool *pool ;
pool = [[NSAutoreleasePool alloc] init];
MyClass *obj;
obj = [[[MyClass alloc ] init] autorelease];
NSLog(@"%@", [obj description]);
NSLog(@"%@", [obj speak:2]);

NSString *s;
int count = 3;
SEL sel = @selector(speak:);
s = objc_msgSend(obj,sel,count);
NSLog(@"%@", s);
[pool drain];
return 0;
}


Note: you have to use an int variable, you can't just pass an int directly to objc_msgSend.
Output:


> ./test
2011-01-27 13:21:37.890 test[38774:903] <MyClass: 0x10010cd20>
2011-01-27 13:21:37.892 test[38774:903] woof-woof
2011-01-27 13:21:37.893 test[38774:903] woof-woof-woof