I'm creating an app in C++ using cocos2d-x. For some integration work, I need to call Objective C code, with an asynchronous response implemented by calling a C++ callback method from Objective C.
TLDR; how should I release the C++ to Objective C bridge whenever the callback finishes? Should I implement the bridge as a static member variable?
For the basic C++ to Objective C part, I've followed Jesús Bosch's lead, for the calling of a C++ callback from Objective C, I've followed his colleagues post.
Basically, I've ended up with the following setup.
First, we have MyApp.h
class MyApp
{
public:
static void buttonChosen(int index);
void callObjC();
// ...
}
and MyApp.cpp
, which is responsible for initiating the Objective C code.
void MyApp::buttonChosen(int index)
{
log("Button choosen: %d", index);
}
void MyApp::callObjC()
{
iOSBridge::iOSHelper* bridge = new iOSBridge::iOSHelper();
bridge->ShowAlert(buttonChosen);
// delete bridge;
}
Then, I have the bridge, iOSBridge.h
namespace iOSBridge{
class iOSHelper {
public:
void(*callback)(int index);
iOSHelper() { }
void ShowAlert(void(*callback)(int));
};
}
and its implementation iOSHelper.cpp
#include "iOSHelper.h"
#import "IsolatedAlert.h"
namespace iOSBridge{
void iOSHelper::ShowAlert(void(*callback)(int index))
{
this->callback = callback;
IsolatedAlert* instance = [IsolatedAlert new];
[instance showAlert: this];
}
}
Finally, there is the IsolatedAlert.h
#import <UIKit/UIKit.h>
#import "iOSHelper.h"
typedef struct iOSBridge::iOSHelper iOsType;
@interface IsolatedAlert : UIViewController
-(void)showAlert:(iOsType*)callback;
@end
and its implementation 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
Now, my question is this: how should I release iOSBridge::iOSHelper* bridge
whenever the buttonChosen()
is called? Is implementing it as a static member ok, as long as I promise not to have more than one instance of MyApp
instantiated at any one time? Thanks!
The usual C++ way of releasing an instance created with new
is to use the delete
keyword:
void MyApp::buttonChosen(int index)
{
log("Button choosen: %d", index);
delete bridge;
bridge = NULL;
}
It is good practice to NULL
the pointer after delete to ensure the application behaves in a consistent manner (crash) in case the object is used after delete
. If you don't do that, your application may seem to work for a while, produce incorrect results, show weird behavior, or crash randomly, or all of the aforementioned.
Ah and of course you should make the bridge pointer a member variable of your App class.
#include "iOSHelper.h"
class MyApp
{
public:
static void buttonChosen(int index);
void callObjC();
// ...
protected:
iOSBridge::iOSHelper* bridge;
}
You should also consider making the existing methods protected
or private
because buttonChosen is probably not a method you want to be able to be called from outside the MyApp instance.