views:

99

answers:

2

I tried this code:

// main.m
#import <stdio.h>

@interface Test 
+ (void)test;
@end
@implementation Test
+ (void)test
{
    printf("test");
}
@end

int main()
{
    [Test test];
    return  0;
}

with LLVM/Clang without any framework, it doesn't compiled with this error:

Undefined symbols:
  "_objc_msgSend", referenced from:
      _main in main.o
ld: symbol(s) not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So I added libobjc.dylib. Code compiled, but threw this runtime exception:

objc[13896]: Test: Does not recognize selector forward::
Program received signal:  “EXC_BAD_INSTRUCTION”.

#0  0x9932a4b4 in _objc_error
#1  0x9932a4ea in __objc_error
#2  0x993212b6 in _objc_msgForward
#3  0x99321299 in _objc_msgForward
#4  0x99321510 in _class_initialize
#5  0x99328972 in prepareForMethodLookup
#6  0x99329c17 in lookUpMethod
#7  0x99321367 in _class_lookupMethodAndLoadCache
#8  0x99320f13 in objc_msgSend
#9  0x00001ee5 in start

I realized some implementation required for root class, but I don't know what should I do next. What's required to make a new root class? And is there any specification for this?

+2  A: 

On the Apple runtime, the minimum specs are pretty easily explained: You have to implement every method in the NSObject protocol. See here. This is absolutely non-trivial. You might want to add a couple of additional functions like +alloc in order to be able to create an instance, etc. There are only two public root classes in all of Apple's frameworks: NSObject and NSProxy. In practice, there is absolutely no reason to create a root class. I'm not sure there is any documentation to this issue by Apple.

What you will do in practice is to inherit from NSObject or NSProxy and build on top of them. Your code will work if you do the following:

@interface Test : NSObject
+ (void)test;
@end

As Tilo pointed out, this is not the case on other runtimes like the GNU runtime.

Max Seelemann
You are right Max: Implementing a new root class is challenging and can be interesting from an academical point of view, but practically there are only very few applications.
GorillaPatch
In reality Apple has created only 5 root classes in all Cocoa frameworks, including nsobject and nsproxy. I never had the need to create one on my own.
Max Seelemann
It was just a kind of trial making objc program on non-Apple platform (like FreeBSD). I agreee with there's no reason to make my own root class in Apple platform :)
Eonil
There are different root classes on different platforms. Most other distributions either include `NSObject` or feature a root class called `object`. YOu might want to google for that...
Max Seelemann
This answer is simply wrong. The above example compiles fine with gcc and GNU-runtime. In Objective-C normally any class can be a root class by simply not having a super class. If the Apple-runtime requires something different, then it's runtime specific.
Tilo Prütz
@Tilo. I find your response a bit drastic, but yes, I assumed the Apple runtime. As assumed he was wanting to target that runtime, since he ran it on there. Is the gnu runtime still being used anyways?
Max Seelemann
@Max: Of course it (the GNU runtime) is :). And maybe I was drastic but I think it should be clearly said that there is a difference between the language Objective-C as understood and processed by the compilers and the different runtimes. And if you'll edit your answer to point this one out I'll take back my down vote :).
Tilo Prütz
There you go ;)
Max Seelemann
And back to the topic: Is the NSObject protocol part of the Apple runtime or of the Foundation Framework? If the latter the runtime should not expect a root class to implement it.
Tilo Prütz
It is part of the framework but it required by the runtime. In fact, a lot of functionality of the runtime is linked to the framework. I'm pretty sure it wouldn't make too much sense to use either separately.
Max Seelemann
Woah! I think that's bad (or at least suboptimal ;)) design. IMHO if framework and runtime require each other they should be put together. At this point the GNU runtime is better. It brings a minimum amount of classes to start with and does not rely on the architecture of a specific framework build on top of it.
Tilo Prütz
Yep, see this the same way. Theoretically one could simply move a few headers and classes out of the framework into the runtime and that'd be fixed...
Max Seelemann
A: 

The above example compiles fine with gcc and GNU-runtime. In Objective-C normally any class can be a root class by simply not having a super class. If the Apple-runtime requires something different, then it's runtime specific.

Additionally there is something specific with root classes:

All instance methods are also class methods with the same implementation (if not explicitly implemented otherwise). The output of the following app:

#import <stdio.h>

@interface Test
+ alloc;
+ (void)test;
- (void)test;
- (void)otherTest;
@end
@implementation Test
+ alloc
{
  return (id)class_create_instance(self);
}

+ (void)test
{
    printf("class test\n");
}

- (void)test
{
    printf("instance test\n");
}

- (void)otherTest
{
    printf("otherTest\n");
}
@end

int main()
{
    id t = [Test alloc];
    [Test test];
    [t test];
    [Test otherTest];
    [t otherTest];
    return  0;
}

would be:

class test
instance test
otherTest
otherTest

The hardest part on creating a new root class is the +alloc and -dealloc but as seen in my example the runtime (in my case the GNU-runtime) can do this. But I don't know if the runtime allocation is good enough. I know that some foundations use an own allocation mechanism to hide the reference counter from the object structure. I don't know if Apple does this too and if their runtime already takes care of it.

Tilo Prütz