3

I am testing some simple Objective-C code on Windows (cygwin, gcc). This code already works in Xcode on Mac. I would like to convert my objects to not subclass NSObject (or anything else, lol). Is this possible, and how?

What I have so far:

// MyObject.h
@interface MyObject

- (void)myMethod:(int) param;

@end

and

// MyObject.m
#include "MyObject.h"

@interface MyObject()
{ // this line is a syntax error, why?
    int _field;
}
@end

@implementation MyObject

- (id)init {
  // what goes in here?
    return self;
}

- (void)myMethod:(int) param {
  _field = param;
}

@end

What happens when I try compiling it:

gcc -o test MyObject.m -lobjc
MyObject.m:4:1: error: expected identifier or ‘(’ before ‘{’ token
MyObject.m: In function ‘-[MyObject myMethod:]’:
MyObject.m:17:3: error: ‘_field’ undeclared (first use in this function)

EDIT My compiler is cygwin's gcc, also has cygwin gcc-objc package:

gcc --version
gcc (GCC) 4.7.3

I have tried looking for this online and in a couple of Objective-C tutorials, but every example of a class I have found inherits from NSObject. Is it really impossible to write Objective-C without Cocoa or some kind of Cocoa replacement that provides NSObject?

(Yes, I know about GNUstep. I would really rather avoid that if possible...)

EDIT This works:

// MyObject.h
@interface MyObject
@end
// MyObject.m
#include "MyObject.h"
@implementation MyObject
@end

Not very useful though...

jscs
  • 63,694
  • 13
  • 151
  • 195
Alex I
  • 19,689
  • 9
  • 86
  • 158
  • 2
    Possibly useful: http://stackoverflow.com/questions/6203467/default-base-class-for-objective-c-classes , http://stackoverflow.com/questions/4295317/what-use-cases-are-there-for-defining-a-new-root-class?lq=1 (note that in this question the new root class still *implements the NSObject protocol*) – user2864740 Oct 20 '13 at 03:55
  • Thanks! Does that mean there is no way to allocate an object without using NSObject, even? Argh... what a screwy language. I don't want to interact with the runtime, or any libraries, I just want to run a completely self-contained, simple piece of code. I guess I can write it in plain C and just call that a .m file, haha. – Alex I Oct 20 '13 at 03:58
  • possible duplicate of [How to instantiate a class in Objective-C that don't inherit from NSObject](http://stackoverflow.com/questions/8954075/how-to-instantiate-a-class-in-objective-c-that-dont-inherit-from-nsobject) – jscs Oct 20 '13 at 04:08
  • The NSObject *protocol* is not the same as the NSObject. That being said, I've never tried :) – user2864740 Oct 20 '13 at 04:09
  • To whoever voted to close: the earlier question only deals with the init/alloc part of this. I am also running into weird compiler issue as you can see. I guess there are two separate questions here, one of which has indeed been answered before. – Alex I Oct 20 '13 at 04:12
  • 1
    Ivars in categories is a Clang-only feature, unless GCC has added it in the very recent past. You need a runtime library, for message dispatch if absolutely nothing else, no matter what you want to do about a root class. The GNU libobjc is part of with GNUStep; I don't know if they're seperable, but they might be. – jscs Oct 20 '13 at 04:36
  • @JoshCaswell: Thanks! I don't need message dispatch, this is as minimal as possible. About libobjc/GNUStep, interesting, but I don't have any headers eg Foundation.h – Alex I Oct 20 '13 at 04:45
  • 1
    You _do_ need message dispatch. That's the fundamental mechanism of Objective-C `[[MyObject alloc] init]` contains _two_ message dispatches. You need `objc_msgSend()`. It may be that your compiler is including libobjc automatically when you compile an ObjC source, unbeknownst to you. – jscs Oct 20 '13 at 04:47
  • Your main compiler problem seems to be what Aaron Golden has pointed out below, however, so far as I can see. – jscs Oct 20 '13 at 04:52
  • 1
    Unfortunately for you, there just aren't many people writing ObjC code for platforms other than Apple's. In theory it's a portable language, because it's just a layer on top of C, but that layer itself has to be ported. I'd suggest looking at either GNUStep's or Apple's root classes for info. (A note; when I said "categories" above, I meant "extensions", which may also not be available via GCC.) – jscs Oct 20 '13 at 04:55
  • @JoshCaswell: Yup, that's what I was afraid of. In theory it's a portable language, but... – Alex I Oct 20 '13 at 05:10
  • Out of curiousity, why do you want to use ObjC? Just trying it out? – jscs Oct 20 '13 at 05:56
  • @JoshCaswell: I have a codebase in ObjC already. It may be better to convert to C, it is not actually that strongly tied to ObjC stuff. – Alex I Oct 20 '13 at 06:55

2 Answers2

2

It's possible to make classes without a base class. There are a couple of things going on. First, your compiler doesn't seem to like the "()" class extension syntax. Other compilers would be OK with it. If you remove those "()" on line four of MyObject.m then your compiler will complain that you've got two duplicate interfaces for the MyObject class. For the purpose of your test you should move that _field variable into the declaration of MyObject in the header file, like:

@interface MyObject {
    int _field;
}
-(void)myMethod:(int)param;
@end

Then you can completely remove that extra @interface in the .m file. That should get you started at least.

jscs
  • 63,694
  • 13
  • 151
  • 195
Aaron Golden
  • 7,092
  • 1
  • 25
  • 31
  • Thanks! Without the parenthesis, I get this: MyObject.m:4:1: warning: duplicate interface declaration for class ‘MyObject’ [enabled by default] MyObject.m:6:1: error: redefinition of ‘struct MyObject’ In file included from MyObject.m:1:0: MyObject.h:3:1: note: originally defined here MyObject.m: In function ‘-[MyObject myMethod:]’: MyObject.m:17:3: error: ‘_field’ undeclared (first use in this function) – Alex I Oct 20 '13 at 03:51
  • I'll try other compilers. Could you also tell me what goes in the init() method of a class without a base class? Thanks again... – Alex I Oct 20 '13 at 03:54
  • 1
    you mean -init? -init usually does nothing but ivar initialization. in this case you may want to define your own init which does nothing and +alloc that allocate memory using malloc or anything. Runtime may require some alignment so.. well, I think you shouldn't waste your time and just simply use GNUstep. Just install the foundation if you don't want GUI. This is a problem far above your experience AFAICT. – Fred Frith-MacDonald Oct 20 '13 at 20:23
  • The class extension (with iVars) syntax is **only** supported in clang, GCC never implemented it. – Richard J. Ross III Oct 25 '13 at 20:03
2

It's possible, but note that NSObject implements the memory allocation API in objective-c, and if you don't implement NSObject's +alloc and -dealloc or equivalent on a root class, you'll still need to implement the same functionality for every class.

James
  • 24,676
  • 13
  • 84
  • 130