Automatic code generation for Objective C to C++ bridge - c++

I am seeking an opinion from the Mac/iPhone developers about a new project. The idea is to start an open source initiative using swig (www.swig.org) for automatically generating the bridge from objective c to c++ so that one can access c++ applications from cocoa/cocoa touch.
Apple provides a very good support for mixing objective c and c++ via objective c++ but writing those bridges by hand could be tedious and bug prone. What this project intend to do is to provide a way of automatically generating objective c interfaces and wrappers over c++ so that any cocoa or cocoa touch application happens to see the object oriented objective c interface with c++ underneath.
I would greatly appreciate any opinion or suggestions over this idea.

I do not think this is necessary. With Objective-C++, you do not need a bridge at all. Given a C++ class defined
class Foo {
public:
void someMethod(void);
}
you can use that class anywhere in Objective-C++ code. For example, within a method:
- (void)myObjCMethod {
Foo myFoo;
myFoo.someMethod();
//etc.
}
You can have instance variables that point to C++ classes, so you could define an Objective-C class like
#interface Bar : NSObject {
Foo *foo;
}
#property (assign) Foo * foo;
#end
#implementation
#synthesize foo;
- (void)dalloc {
delete foo;
[super dealloc];
}
- (id)init {
if(self = [super init]) {
foo = new Foo();
}
return self;
}
- (void)aMethod {
self.foo->barMethod();
}
I don't think you can template an Objective-C method, but C++ template instantiations in Objective-C++ are fair game. Just as Objective-C is a strict superset of C, Objective-C++ is a superset of C++, adding Objective-C-style classes and message passing.
If you did want to "bridge" a C++ class, you're going to have trouble in general, since things like multiple inheritance and operator overloading aren't supported in Objective-C's object model.

It strikes me as a good enough idea that I'd be surprised if something like it doesn't already exist. On the other hand, since you can compile C++ directly, (look at what a .mm extension gives you) it might be somewhat trivial.

Related

How to pass a callback function from C++ to Objective-C

I don't want to use NSNotification because it is so messing up internally. Is it a way to pass a callback function from C++ to Objective-C++, and let Objective-C call it?
The problem is that I don't know how to pass a function written in C++ to Objective-C++, and how could I use that callback in Objective-C++? Is it a pointer?
I know I can mix them up but my class has to be a C++ class because it inherits some C++ classes.
You're not 100% specific as to the exact use case you're trying to cover here, but I'm going to set out a scenario where this kind of situation occurs, and then show you how to solve it. I hope that will cover your problem too.
So I'm going to assume you have an Objective-C class MyClass with its interface declared in MyClass.h:
#interface MyClass : NSObject
- (void)someMethod;
- (void)otherMethodWhichShouldTakeACallback:?????;
#end
You now have a C++ class MyCPPClass, declared in MyCPPClass.hpp on which you want to pass memberFunction as the callback argument to the otherMethod on MyClass:
class MyCPPClass : public MyBase
{
void memberFunction();
};
First, we need to figure out the method signature on MyClass. The modern way for callbacks in Objective-C is with Blocks. Blocks work pretty well with Objective-C++, so let's go with that and modify MyClass.h with the following line:
- (void)otherMethodWithBlock:(void(^)(void))callbackBlock;
The calling code will need to reside in an Objective-C++ compilation unit (caller.mm):
void callOtherMemberWithCPP(MyCPPClass* cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
Note that this does not deal with object lifetimes. If you're managing lifetimes on the C++ side with std::shared_ptr, you can use that in your Objective-C++ code too, in which case we might end up with something like:
void callOtherMemberWithCPP(std::shared_ptr<MyCPPClass> cpp_obj, MyClass* objc_obj)
{
[objc_obj otherMethodWithBlock:^{
cpp_obj->memberFunction();
}];
}
In this case, the C++ object will only have its reference count decremented when the Objective-C class is done with the block.
For completeness, the other way to do this would be to use C function pointer syntax. In this case, you would need to declare the Objective-C method along these lines:
- (void)otherMethodWithCallback:(void(*)(void*))callback object:(void*)opaqueCallbackArgument;
And the C++ class's method call would need to be wrapped in a free function or static member function:
void memberFunctionCallback(void* opaque_object)
{
MyCPPClass* object = static_cast<MyCPPClass*>(opaque_object);
object->memberFunction
}
…and then call the Objective-C method like this:
[objc_obj otherMethodWithCallback:memberFunctionCallback object:cpp_obj];
Making this version work nicely with automatic lifetime mechanisms such as shared_ptr is a lot more tricky though.

Calling an Objective-C Method from a purely C++ class

I have a pure C++ class that needs to retrieve an int value from some Objective-C instance method.
I understand that C++ cannot call Objective-C methods directly.
I have an Objective-C++ class that allows me to work with Objective-C and also to pass data to my pure C++ class.
However, I have not figured out a way to allow the pure C++ class to request the int value be computed and retrieved. In other words, the pure C++ needs to be able to retrieve that value whenever it needs to (via a function pointer, or whatever).
Anyone know how this is accomplished?
C++ can definitely call Objective-C code. Store the code that communicates in a .mm file instead of .cpp, and Xcode will do the rest for you.
.mm files store Objective-C++ code, which is why it works.
[Edit]
You probably have some business logic in C++, and want to combine that with your UI in Objective-C, right? Your business logic is probably shared across multiple platforms, which is why you can't just compile all your code as Objective-C++.
That's why you can basically "wrap" your Objective-C code in an Objective-C++ wrapper.
// myUI.h (C++ header)
class myUI {
void doSomething1();
int doSomething2();
}
// main.cpp (C++ code)
int main() {
myUI ui;
printf("%d\n", ui.doSomething2());
ui.doSomething1();
return 0;
}
// myUI.mm (Objective-C++ code)
int myUI::doSomething2() {
return [[MyController sharedController] doSomething2];
}
// myUI.cpp (C++ code)
void myUI::doSomething1() {
printf("Hi!\n");
}

Objective C++ call Objective C

I have a growl action I need to call from Objective C++
- (NSDictionary *) registrationDictionaryForGrowl {
return [NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithObject:#"Alert"], GROWL_NOTIFICATIONS_ALL,
[NSArray arrayWithObject:#"Alert"], GROWL_NOTIFICATIONS_DEFAULT
, nil];
}
is the action in Objective C, but I need to put it in a .mm file (Objective C++) and I'm having a hard time trying to convert it properly because I need to put it inside a (C++) function inside a (C++) class.
Any idea how I could transfer this over to Objective C++?
From what I gather you want to provide a C++ object to Growl, which expects and Objective-C object. You can't do this.
Objective-C is a set of language extensions welded onto C. Objective-C++ is the result of welding exactly the same extensions onto C++. So in Objective-C++ you have both Objective-C style objects and C++ objects, and they are completely different things. One cannot be used when the other is expected. They have different ABIs, different schemes for resolving a method call/message send, different lifetime management, etc.
The purpose of Objective-C++ is not to make Objective-C objects and C++ objects compatible, but simply to make Objective-C code usable from C++ and C++ code usable from Objective-C++.
So what you could do is create your C++ class that you want to use as a delegate, and then create an Objective-C++ class that wraps your C++ class and has methods that simply forward to an instance of your C++ class.
class Foo {
int bar(int i) { return i+1; }
};
#interface ObjCFoo : NSObject
{
Foo foo;
}
- (int) bar:(int) i;
#end
#implementation ObjFoo
- (int) bar:(int) i;
{
return foo.bar(i);
}
#end
In Objective-C++ there are C++ classes and Objective-C classes. There are no Objective-C++ classes. The GrowlApplicationBridgeDelegate which implements registrationDictionaryForGrowl has to be an Objective-C object. You can define it exactly same in an .mm file as you would in an .m file. The only difference is that in your .mm file the Objective-C classes you define can call and use C++ classes and syntax.
I do not know what do you call Objective-C++, but the code above, provided it is in an Objective-C #implementation section, will compile fine with or without Objective-C++ enabled (.m or .mm extension).
By the way, if you are using Xcode 4.4 or above, the following will do as well:
- (NSDictionary*) registrationDictionaryForGrowl {
return #{
GROWL_NOTIFICATIONS_ALL : #[ #"Alert" ],
GROWL_NOTIFICATIONS_DEFAULT : #[ #"Alert" ] };
}

Calling an Objective-C class method from C++

I am having some trouble calling an objective-c class method from a C++ file. Example:
In my .h:
#interface MyClass : NSObject {
}
+ (void)myMethod:(NSString *)str;
In my .m:
+ (void) myMethod:(NSString *)str { ... }
In my .cpp:
??
How can you call myMethod since there is no class instance? Its essentially a static?
Thanks
Objects in C++ are incompatible with objects in Objective-C. You cannot simply call an Objective-C method from C++.
There are some solutions, however:
Use Objective-C++. Rename your .cpp to .mm, then you can use Objective-C syntax in your C++ code: [FlurryAnalytics myMethod: #"foo"];
Use direct calls to the Objective-C runtime system. I won't tell you how to, because I really think you shouldn't, and in fact that you don't want to.
Write a plain-C interface. That is, in some .m file, define void myFunction(const char *str) { ... } and call that from C++. You can find an example of this here.
You're going to need a .mm to call an Objective-C method, rather than a .cpp. Beyond that your comment that 'it's essentially static' is accurate in the sense that you would call it with similar logic to the way you would call static class functions in C++:
[MyClass myMethod:#"Some String"];
Though the method isn't static in the C++ sense for a bunch of reasons that don't affect this answer — it isn't resolved at compile time and it does operate within a class (the MyClass metaclass).

Objective C ViewController with a C++ object as a property has getters and setters that re-initialise it every time it's referenced

I have tried so many combination's of code I don't have a sample to show.
I have a Objective C view controller, and in the interface I declare a C++ class that contains the preferences of what the user wants to have. I do my #property command in the header and #synthesize command at the top of the .mm file.
Then I use the class in the loadView method and it initialises, which is a good thing and I load all the preferences into the class exactly how I want them to go, which is all fine.
Then down in the other methods such as numberOfSectionsInTableView and numberOfRowsInSection, etc, I go to use the class to retrieve the values, and this goes wrong.
The class initialises every time I go to use it. So when want to know how many groups in the preference file, the C++ method I called countGroup, it just reinitialises everything and there is no longer any data in my C++ class.
What I think, is that the #property command has generated the getters and setters in a way that specifically reinitialises classes. This is just a guess but if I'm right how do I over write them or is there some other way of using my C++ class globally through out my view controller.
Note: the C++ class doesn't work if it's referenced as a pointer because it's got loads of nested vectors and stuff, the compiler just throws a wobbly at that.
I had a similar story to you where I tried to use boost shared pointers and weird and crazy stuff kept happening.
Objective-C++ just doesn't work by the same rules as C++. The memory scope rules of C++ classes are not covered by Obj-C++. Things like smart pointers and vectors just won't work properly in Obj-C++.
The way that I got around it was to write a very simple container class:
class MyContainerClass
{
public:
boost::shared_ptr<MyClass> mySharedPointer;
/// etc
};
Then in my Obj-C++ code I'd allocate/free the above the Obj-C++ way:
- (id)init
{
if (self = [super init])
{
myContainer = new MyContainerClass();
// etc
}
return self;
}
and
- (void)dealloc
{
// etc
delete myContainer;
[super dealloc];
}
Then I'd have an accessor like:
- (boost::shared_ptr<MyClass>)mySharedPointer
{
return myContainer->mySharedPointer;
}
It's an ugly approach but it's the only way I could figure out how to get around this issue.