Hacker News new | ask | show | jobs
by frou_dh 5228 days ago
Is it possible to see this straight C translation? Using Clang for example. I'm sort of aware of the "objc_msgSend" business, but would like to see more.

Talking of OpenStep, after seeing some of those NeXT videos on HN the other day, I found a torrent of OpenStep 4.2 incl the dev tools. It's a VMware image and boots and runs just fine. Pretty nifty. Then I noticed OpenStep 5.0 redirects to Mac OS X on Wikipedia!

2 comments

Quick example of calling a method that doesn't take any arguments and returns an object:

  id foo = [self bar];
is the same as:

  id foo = self.bar;
which is also the same as:

  id foo = [self performSelector:@selector(bar)];
or:

  IMP barImp = [self methodForSelector:@selector(bar)];
  id foo = barImp(self, @selector(bar); [1]
and finally:

  id foo = ((id)(id, SEL)objc_msgSend)(self, @selector(bar)); [2, 3, 4]
1. Because we're calling the IMP, or implementation, directly, we don't need a cast (like we do below, with objc_msgSend).

2. Casting the function is optional, but, helps to prevent things like endian differences and your return value getting mangled when using the same code on PPC and Intel. Not too big of a deal anymore.

3. There are actually two other varieties of objc_msgSend, depending on your return type — specifically, floating point calls should use objc_msgSend_fpret and calls that return a struct should use objc_msgSend_stret.

4. I hope I got this cast right, I didn't try to compile it.

Those first two and following aren't equivalent, are they? Wouldn't they compile, respectively, to:

    objc_msgSend(self, @selector(bar));
And:

    objc_msgSend(self, @selector(performSelector:), @selector(bar));

?
The first two are the same, with a different syntax, yes.

They would both become:

  objc_msgSend(self, @selector(bar));
However, your examples are basically explicitly passing a message (1 and 2), vs dynamically building a message to pass (3).

For the second to work, the objc_msgCall function would really be:

  objc_msgSend(self, @selector(performSelector:), @selector(bar));
(The first example is saying to self to call the selector (method) named 'bar'. The second example is telling self to call the method 'performSelector:' with an argument of 'bar'.)

The runtime may or may not be smart enough to optimize this out. It has never been a bottleneck for me to bother looking into it, and I haven't come across anything to indicate one way or the other.

Check out clang's -rewrite-objc option. It outputs C++, not C, and isn't entirely truthful since Obective-C is compiled directly these days, but should give you what you're after.