An idea, Obj-C and C++collide

Posted on May 4, 2008 1:30 PM.
The entry before this one was The Twitter Shanghai and the next one is Perspiration and Inspiration.

I finally came up with an original game idea that I actually want to pursue. A couple of days ago, I embarked on making a prototype. Now, if I were all about just getting a game done, I'd prototype in Java or Flash (*HORF*). But since I'm a total nerd, the prototype is also an exercise in getting to know Xcode and finally getting back into writing some actual game related code.

I didn't want to start totally from scratch, so I elected to use SDL since they provide nice little Xcode templates that takes care of the boilerplate stuff such as opening a window, initializing graphics & sound, getting the mouse & keyboard, etc. Plus, if I decide to use this library in the production code, there's a good chance that I could port to other platforms later on rather easily. Unless I decide to heavily use Apple specific APIs and Objective-C. Which isn't out of the question.

I downloaded a sample application from Apple that demonstrates OpenGL running in an OS X application. It had along with it a really nifty bit of code that rendered text from the Quartz system into an OpenGL texture. Being able to render text to the screen when debugging a game is extremely useful. I decided I would try to use this class in my prototype. The only trick is this code is written in Objective-C and my code is in C++.

From looking at the SDL provided application template, I already saw that Obj-C and C++ could be compiled and linked together. There's tons of examples online of calling C++ code from within Objective-C, but I couldn't find a definitive example of a C++ class using an Objective-C class. Maybe it's just dumb obvious and I wasn't seeing it. Regardless, I set out to do it on my own. I decided to exploit the ability of both Obj-C and C++ to declare and use C structs. After an hour of tinkering, it worked! the best part is that I didn't need to modify the Obj-C code at all. I really didn't have any reference to go on here, so it could be really wrong and bad. But here's the general idea:


// ObjCObject.h 
@interface ObjCObject : NSObject 
{}
- (void) doSomething;
@end

// ObjGlue.h
extern "C" { void InitObjGlue(); void UninitObjGlue(); } // sets up the memory pools
class ObjGlue
{
   private:
      void* m_Impl;
   public:
      ObjGlue();
      ~ObjGlue();
      void doSomething();
};

// ObjGlue.cpp <- Set the project to compile as Obj-C code
// These are called in your C++ code before using the wrapper class
void UninitObjGlue() { [gPool release]; }
void InitObjGlue() { UninitObjGlue(); gPool = [[NSAutoreleasePool alloc] init];

struct ObjGlueImpl // must be plain old data
{
   id _baseObj;
};

#define IMPL ((ObjGlueImpl*)m_Impl)

ObjGlue::ObjGlue() 
{
   m_Impl = malloc(sizeof(ObjGlueImpl)); //can't use operator new
   m_Impl->_baseObj = [[[ObjCObject alloc] init] autorelease];
}
ObjGlue::~ObjGlue()
{
   free(m_Impl);
}
void ObjGlue::doSomething() { [IMPL->_baseObj doSomething]; }  

// your cpp code (InitObjGlue was called earlier!)
ObjGlue obj;
obj.doSomething();

So the memory pool stuff is a little funky. I supposed I could create an autorelease pool per object instance, but that seems a bit much. To be honest, I'm not 100% sure I need the autorelease pool at all. This is truly the first Obj-C code I've actually written. But it's my understanding that because I'm using a Foundation/Cocoa class (NSObject), I have to send the release message instead of the typical free. Anybody confirm that?

I wouldn't feel totally confident shipping code with this without some more testing and profiling. But it does in fact work for my uses and that's good enough for now.


Back To Home ScrewTheMan.com Logo - Screw working for The Man!