Objective-C to C++ callbacks - Plunge Interactive

Objective-C to C++ callbacks

As we are currently working with some cross-platform games with cocos2d-x (c++) that have facebook (native SDK) features we’ve been working on a way of communicating them. In this post I will talk about how we managed to make calls from C++ to Obj-C that throw some events in Obj-C and be able to propagate the events to C++.

As this is a two way trip (C++ -> Obj-C, Obj-C -> C++) and I’m only going to focus on the second part I recommend you to read this post on how to get the first part working.

By now you should be able to make calls to a Objective-C++ “bridge” class that calls Objective-C code. We have (at least!) two options:

  1. Pass a function pointer as parameter to the bridge so it can be called as an event
  2. Pass an object as parameter to the bridge so you can call it’s methods

We’ll start with the first one, that has the limitation that as we don’t have any instance of the class the method has to be static, but it’s easier to implement:

In our c++ normal class from where we will call the bridge functions we have the method to be executed:

class.h:

 static void buttonChoosen(int index);

class.cpp:

void Class::buttonChoosen(int index)
{
    CCLOG("Button choosen: %d", index);
}

This method will be called when the user presses a button from the native alert message box. As you can see we use the CCLOG (from cocos2d-x) to make sure the method is executed and gets the pressed button index.

Attention: The following code will be Obj-C++!
iOSHelper.h:

class iOSHelper
{
public:
    void(*callback)(int index);

    iOSHelper() { }
    void ShowAlert(void(*callback)(int));
};

As field we store a function pointer that will be passed as parameter to the ShowAlert() method. This function will be executed when the alert Obj-C callback is called.

iOSHelper.mm:

#import "iOSHelper.h"
#import "IsolatedAlert.h"

void iOSBridge::iOSHelper::ShowAlert(void(*callback)(int index))
{
    this->callback = callback;

    IsolatedAlert* instance = [IsolatedAlert new];
    [instance showAlert: this];
}

Notice that we pass as parameter the bridge itself (this) to the showAlert Obj-C method.

IsolatedAlert.h:

#import <UIKit/UIKit.h>
#import "iOSHelper.h"

typedef struct iOSBridge::iOSHelper iOsType;

@interface IsolatedAlert : UIViewController

-(void)showAlert:(iOsType*)callback;

@end

IsolatedAlert.mm:

#import "IsolatedAlert.h"

iOsType* staticPointer;

@implementation IsolatedAlert

-(void)showAlert:(iOsType*)callback
{
    staticPointer = callback;

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Title?"
                                                    message:@"Message?"
                                                   delegate:self
                                          cancelButtonTitle:@"Cancel"
                                          otherButtonTitles:@"OK", nil];
    [alert show];
    [alert release];
}

-(void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    staticPointer->callback(buttonIndex);
}

@end

Show alert method saves the pointer to the bridge class so the clickedButtonAtIndex method can call the callback to our C++ static method where we can execute our code normally.

That’s all for the first option. For the second one I will not write all the code (as it’s pretty similar), but talk about the differences. Feel free to ask on the comments if anything is not clear enough!

To be able to call an event method we will define an abstract class (in C++) for every task the bridge needs to perform.
For example an AlertCallback.h:

class AlertCallback
{
public:
    void buttonChoosen(int index) = 0;
};

If a normal C++ class wants to be able to get the callback from an alert it will need to inherit this class and implement all the methods (this only has one, but a others could require more).

In the bridge we won’t store a function pointer but a pointer to an AlertCallback which is the latest instance that called the showAlert. Notice that polymorphism allow us to have as a field a pointer to an abstract class and store there a pointer to a class that inherits from it.

From the clickedButtonAtIndex method we will be able to call all the member methods of the AlertCallback (only one) as we have a pointer to an instance of it.

And that’s all for this post, have a nice weekend!

This site uses cookies to store information on your computer. Some cookies on this site are essential, and the site won't work as expected without them. Read more about them

ACCEPT