Monday, December 22, 2008

I've Bridged The Gap

I spent a few hours fooling around with the iPhone Views, and decided let me try the Objective-C/C++ bridging.  Well, it works like a charm.  I took the little test sample on the Apple Dev. Page and added some things I wanted to see if they would work.

Here's what I did...

// header file mixing C++ and Objective-C
// wouldn't want to really do this...keep the interface files separate for each class. 
// I just did it this way for sample/quick test purposes
// test.h

class Hello
{
private:
id greeting_text;

public:
Hello()
{

greeting_text = @"Hello, world!";
}

Hello(const char* initial_greeting_text)
{
greeting_text = [[NSString alloc] initWithUTF8String:initial_greeting_text];

}

void say_hello()
{
printf("%s\n", [greeting_text UTF8String]);
}

};

@interface Greeting : NSObject
{

@private
Hello *hello;
}

- (id) init;
- (void) dealloc;
- (void) sayGreeting;
- (void) sayGreeting:(Hello*)greeting;

@end

@implementation Greeting

- (id) init
{
if(self = [super init])
{
hello = new Hello();
}

return self;
}

- (void) dealloc
{
delete hello;
[super dealloc];
}

- (void) sayGreeting
{
hello->say_hello();
}

- (void) sayGreeting:(Hello*)greeting
{
greeting->say_hello();
}

@end


//
// C++ translation, Objective-C implementation, and main
// (again mixed together for easy reading)
//

#import
#include "test.h"
#include

int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// notice here...dynamic typing
std::vector testVector; // holds generic objects
id szTest = @"'ello Gov'ner!"; // Obj-C NSString (declared as a dynamic type)

// testing in new C++ casting works in mixed Obj-C/C++
float fTest = 9.0f;
int nTest = static_cast(fTest); // it does
printf("nTest = %d\n", nTest);

// instantiate the Greeting class
Greeting *greeting = [[Greeting alloc] init];

// test to see if I can use STL
testVector.push_back(greeting);
testVector.push_back(szTest);
printf("number of objects in the vector = %d\n", testVector.size());

// get the "sayGreeting" method from the Greeting class
SEL action = @selector (sayGreeting);
id tempObj;

short i = 0;
for(std::vector::iterator it = testVector.begin(); it != testVector.end(); it++)
{
printf("In vector loop = %d\n", i++);

// set the temp object
tempObj = *it;

// check to see if the object is our Greeting object
if( [tempObj respondsToSelector: action] == YES )
[*it sayGreeting];
else
printf("%s\n", [*it cString]); // it is our other object
}

// can also do C++ straight up
Hello *hello = new Hello("Bonjour, monde!");

// then mix it with Obj-C
[greeting sayGreeting:hello];

delete hello;
[greeting release];

[pool release];

return 0;
}

As you can see, you can mix the two together and also, take advantage of the dynamic typing in STL containers.  However, be careful as Ondra Cada, explained to me that you have to be weary about the memory management issues of Objective-C and garbage collection, if you leave an object around in a container for sometime and not use it, it could get thrown out, and well...leave you hanging (come on people, work with me).  Instead of using the STL Vector, you should use the NSArray in the Foundation class. 

I did this way to see what is possible with the language...I like it.  The built in "reflection," is fabulous, no fooling around with templates.

Okay, that's it for tonight (ahh morning).  Tomorrow, I will do a quick little test of archiving, writing/reading objects of diff types in/out.  Also, taking advantage of the Foundation class ability to serialize via XML and binary.  This is great for debug and release.  In debug you can XML to verify the data is correct, and then bundle it up in binary form for release.

Going to sleep.

No comments: