Writing a C++ Wrapper around Objective-C - c++

I want to call and work with Objective-C classes from within a C++ project on OS X. It is time to start moving towards all Objective-C, but we need to do this over some time.
How does one go about accomplishing this? Can anyone shed some light and provide an example?

Objective-C++ is a superset of C++, just as Objective-C is a superset of C. It is supported by both the gcc and clang compilers on OS X and allows you to instantiate and call Objective-C objects & methods from within C++. As long as you hide the Objective-C header imports and types within the implementation of a C++ module, it won't infect any of your "pure" C++ code.
.mm is the default extension for Objective-C++. Xcode will automatically do the right thing.
So, for example, the following C++ class returns the seconds since Jan 1., 1970:
//MyClass.h
class MyClass
{
public:
double secondsSince1970();
};
//MyClass.mm
#include "MyClass.h"
#import <Foundation/Foundation.h>
double MyClass::secondsSince1970()
{
return [[NSDate date] timeIntervalSince1970];
}
//Client.cpp
...
MyClass c;
double seconds = c.secondsSince1970();
You will quickly find that Objective-C++ is even slower to compile than C++, but as you can see above, it's relatively easy to isolate its usage to a small number of bridge classes.

I think it was Phil Jordan that really put forward the best C++ wrapped Obj-C formula. However, I think the latter, C++ wrapped by Obj-C is more useful. I'll explain why below.
Wrapping an Objective-C object with C++
Person.h - The Obj-C header
#interface Person : NSObject
#property (copy, nonatomic) NSString *name;
#end
PersonImpl.h - The C++ header
namespace people {
struct PersonImpl;
class Person
{
public:
Person();
virtual ~Person();
std::string name();
void setName(std::string name);
private:
PersonImpl *impl;
};
}
Person.mm - The Obj-C++ implementation
#import "Person.h"
#import "PersonImpl.h"
namespace people {
struct PersonImpl
{
Person *wrapped;
};
Person::Person() :
impl(new PersonImpl())
{
impl->wrapped = [[Person alloc] init];
}
Person::~Person()
{
if (impl) {
[impl->wrapped release]; // You should turn off ARC for this file.
// -fno-objc-arc in Build Phases->Compile->File options
}
delete impl;
}
std::string Person::name()
{
return std::string([impl->wrapped UTF8String]);
}
void Person::setName(std::string name)
{
[impl->wrapped setName:[NSString stringWithUTF8String:name.c_str()]];
}
}
#implementation Person
#end
Wrapping a C++ object with Objective-C
I often find the real problem isn't getting C++ to talk to Obj-C code, it's switching back and forth between the two where things get ugly. Imagine an object that needs to have C++-only items, but the basic object details are filled out in Obj-C land. In this case, I write the object in C++ and then make it so I can talk to it in Obj-C.
Person.h - The C++ header
namespace people
{
struct PersonImpl;
class Person
{
public:
Person();
Person(Person &otherPerson);
~Person();
std:string name;
private:
PersonImpl *impl;
}
}
Person.cpp - The C++ implementation
namespace people
{
struct PersonImpl
{
// I'll assume something interesting will happen here.
};
Person::Person() :
impl(new PersonImpl())
{
}
Person::Person(Person &otherPerson) :
impl(new PersonImpl()),
name(otherPerson.name)
{
}
~Person()
{
delete impl;
}
}
Person.h - The Obj-C header
#interface Person : NSObject
#property (unsafe_unretained, nonatomic, readonly) void *impl;
#property (copy, nonatomic) NSString *name;
#end
Person.mm - The Obj-C++ implementation
#interface Person ()
#property (unsafe_unretained, nonatomic) std::shared_ptr<people::Person> impl;
#end
#implementation Person
- (instancetype)init
{
self = [super init];
if (self) {
self.impl = std::shared_ptr<people::Person>(new people::Person());
}
return self;
}
- (instancetype)initWithPerson:(void *)person
{
self = [super init];
if (self) {
people::Person *otherPerson = static_cast<people::Person *>(person);
self.impl = std::shared_ptr<people::Person>(new people::Person(*otherPerson));
}
return self;
}
- (void)dealloc
{
// If you prefer manual memory management
// delete impl;
}
- (void *)impl
{
return static_cast<void *>(self.impl.get());
}
- (NSString *)name
{
return [NSString stringWithUTF8String:self.impl->name.c_str()];
}
- (void)setName:(NSString *)name
{
self.impl->name = std::string([name UTF8String]);
}
#end
Regarding the void *
The second you stepped into the land of C++ you were going to feel some pain if you want to avoid your whole project being littered with .mm files. So, let's just say, if you don't think it is ever necessary to get your C++ object back out, or reconstitute the Obj-C object with the C++ object you can remove that code. It is important to note that the second you remove the Person instance from the Obj-C code through the void * method you had better make your own copy with the copy constructor or the pointer will become invalid.

First rename your files from *.m to *.mm so you get Objective-C++
I have not tired this, so it is speculation (I will tonight):
As all Objective-C++ objects (that are reference counted) are controlled via pointers so you can write a special destructor for shared pointer.
template<typename T>
struct ObjCDestruct
{
void operator()(T* obj)
{
[obj release];
}
};
Now you can stick your Objective-C obects in a boost::shared_ptr
// FuncFile.M
//
int func()
{
boost::shared_ptr<MyX, ObjCDestruct<MyX> > data([[MyX alloc] init]);
[data.get() doAction1:#"HI"];
}

Check out this question Calling Objective-C method from C++ method?
You will need to have some objective-c classes to wrap the code and expose with a C function.

Related

Calling objective C method from c++ class method

Is it possible to call an objective C method from a C++ class method? I am aware this has been answered to an extent but none of the accepted answers appear to be working for me as I get 'use of undeclared identifier' when trying to use the objective C instance variable (a pointer to self) to call the method.
#interface RTSPHandler : NSObject {
id thisObject;
}
implimentation:
-(int)startRTSP:(NSString *)url {
thisObject = self;
// start rtsp code
}
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned ) {
[thisObject receivedRTSPFrame:fReceiveBuffer];
}
-(void)receivedRTSPFrame:(NSMutableData* )data {
// decode frame..
}
error: use of undeclared identifier 'thisObject'
Try to declare thisObject as a static variable like below
static id thisObject;
#implementation RTSPHandler
//...
#end
UPDATE
Ok. Now I see my answer is hilarious. Let's get through the task and make the solution more appropriate.
There will be two separate classes with separated interface and implementation parts. Say the objective-c class named OCObjectiveClass (Objective-c class) and DummySink (C++ class). Each DummySink instance must have an object of OCObjectiveClass as a c++ class member.
This is interface part of OCObjectiveClass (with a ".h"-extension):
#interface OCObjectiveClass : NSObject
//...
- (void)receivedRTSPFrame:(void *)frame; // I don't know what is the frame's type and left it with a simple pointer
//...
#end
This is the interface part of DummySink (with a ".h"-extension too):
#import "OCObjectiveClass.h" // include objective-c class headers
class DummySink
{
OCObjectiveClass *delegate; // reference to some instance
//...
void AfterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,struct timeval presentationTime, unsigned);
//...
}
AfterGettingFrame function realization must be in DummySink class implementation part (not ".cpp" extension, it must be ".mm" to work with objective-c classes and methods).
void DummySink::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
struct timeval presentationTime, unsigned ) {
[delegate receivedRTSPFrame:fReceiveBuffer];
}
Don't forget to set the delegate value.
- (void)someMethod
{
OCObjectiveClass *thisObject;
// initialize this object
DummySink sink;
sink.delegate=thisObject;
sink.DoWork();
}

How to call C++ method from Objective-C Cocoa Interface using Objective-C++

Right now my OS X 10.9 project is set up with a GUI in Objective-C and all the processing in a C++ class. This doesn't seem like the best way, but this was given to me and I have to work with these constraints. I currently have a NSSlider in the Cocoa GUI. I want to be able to have this NSSlider control a variable x in the C++ class.
Currently the tolerance bar is working when I run the program (working meaning it's continuously updating its value as per my sliding).
Header for NSSlider (Slider.h):
#interface Slider : NSObject {
#private
__weak IBOutlet NSTextField *sliderValue;
__weak IBOutlet NSSlider *slider;
}
- (IBAction)updateSliderValue:(id)sender;
#end
Implementation for the NSSlider (Slider.mm):
#import "Slider.h" // The NSSlider object
#import "CMain.h" // The C++ class that does all the processing (not sure if this is the way to include a C++ interface in an Objective-C++ class or if this will allow me to call its methods)
#implementation Slider
-(void) awakeFromNib {
[slider setIntValue:40];
[sliderValue setIntValue:[slider intValue]];
}
- (IBAction)updateSliderValue:(id)sender {
[sliderValue setIntValue:[slider intValue]];
// Here is where I'd think that if I have a setValueofX(int number) method in the C++ class
// I could call this somehow using objective-C++. I don't know if I can or how to call this method here
}
Here is the relevant snippet from Main.h:
class CMain(){
public:
CMain();
void setValueofX(int number);
int getValueofX();
private:
int x;
};
How do I include CMain.h in the Objective-C++ (which, the .h file or .mm file? and how?) such that it would allow me to call the methods in CMain.h? How would I phrase the method call in Objective-C to set x's value using the setValueofX(sliderValue)?
Please let me know if more information is needed! Any help or thoughts are appreciated!
Thanks!
The code for calling the setter is the same as it would be in C++. However, you'd need a pointer to the CMain object to be able to call the method on it. I don't know where that object currently resides. If there is no object yet in another object, you probably want to create one, which you can by just declaring an instance variable CMain myCMain; and then calling myCMain.setValueOfX( [slider intValue] ); in updateSliderValue:.
As to where to include the C++ class, it's really your choice. However, if you use any C++ in your header, it will take a bunch of careful extra work to include it from plain .m files. So in general I try to stick to plain C and ObjC in the header, and only use C++ in the .mm file. You can use a class extension (sometimes called "class continuation" as well) to declare additional ivars in your .mm file to keep them out of the header.
If you want more info about ObjC++, I answered in detail on another post: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link? and that also links to a Podcast I was a guest on where I talk about a lot of the details and tricks for integrating ObjC and C++.
Aside: I hope these are not actual names and comments you're using. Never have an ObjC class without a prefix (3 letters, Apple stated they reserve all 2-letter prefixes for their own use, and they've used un-prefixed internal class names in the past which broke some peoples' programs). Also, "Slider" is a bad name, as NSSlider is the actual slider, and this sounds like it should be a subclass. You really want to call this an ISTSliderController or whatever.
I found a solution by noting that there was an existing wrapper class CWrapper.h and it was an objective-C++ implementation class CWrapper.mm. There was a CMain variable instantiated as cmain. I made a getter method for x and I simply created a static method in the wrapper class + (void) passX:(int) number; that I called in the slider class. I chose a static method because this for this application, this value will never have to be different between objects. I hope I made the right choice here!
See code changes below:
I added this to the Slider.h file.
- (int)X;
I added the getter and [CWrapper passX:[self getX]]; to the updateSliderValue method in the Slider.mm file.
- (int)X {
return [slider intValue];
}
- (IBAction)updateSliderValue:(id)sender {
[sliderValue setIntValue:[slider intValue]];
[CWrapper passX:[self getX]];
}
This is the code I added to CWrapper.h.
+ (void) passX:(int) number;
This is the code I added to CWrapper.mm.
+ (void) passX:(int)num
{
cmain.setValueofX(num);
}
Here's an all objective-c and objective-c++ answer:
CMain.h:
#ifndef Testing_CMain_h
#define Testing_CMain_h
#interface CCMain : NSObject
-(CCMain*) init;
-(void) dealloc;
-(void)setValueofX:(int)number;
-(int)getValueofX;
#end
#endif
CMain.mm:
#import <Foundation/Foundation.h>
#import "CMain.h"
class CMain {
private:
int x;
public:
CMain() : x(0) {}
void setValueofX(int number) {x = number;}
int getValueofX() const {return x;}
};
#interface CCMain ()
#property (nonatomic, assign) CMain* inst;
#end
#implementation CCMain
-(CCMain*) init
{
if (!_inst)
{
_inst = new CMain();
}
return self;
}
-(void) dealloc
{
delete _inst;
_inst = nil;
}
-(void)setValueofX:(int)number
{
_inst->setValueofX(number);
}
-(int)getValueofX
{
return _inst->getValueofX();
}
#end
and if you want to use C-style functions then:
setValueofX(cmain_instance, value);
int val = getValueofX(cmain_instance);
And this works because a C++ class function in C is the same as:
void CMain::MyFunc(int X);
//vs..
void MyFunc(CMain* inst, int X);
Both are the exact same thing.

How to release bridge object after C++ callback is called from Objective C

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.

Return Obj-C blocks in C++ code

I'm currently porting some classes from the Apple iOS Foundation Framework to C++ and i'm expecting some issues. I'm trying to port this Obj-C method from the NSExpression #class :
- (id, NSArray *, NSMutableDictionary *)expressionBlock
So in my sfExpression class, I have the following code (when deleting others methods ^^)
class sfExpression : public sfObject {
public:
id (^ExpressionBlock())(id, NSArray*, NSMutableDictionary*);
private:
NSExpression* _Expression;
};
And when I'm trying to implement this function like this :
id (^sfExpression::ExpressionBlock())(id, NSArray*, NSMutableDictionary*) {
return [_Expression expressionBlock];
}
It doesn't work... Any ideas ?
I've tried many things but... without success :'(
EDIT : The code is right. Just switch to LLVM Compiler instead of GCC
Edit: Moral of the story, don't use GCC when dealing with blocks.
Here is a full example as far as I can see, this works in my tests.
class Foo
{
public:
Foo(NSExpression *_exp) : expression([_exp retain])
{
}
~Foo()
{
[expression release];
}
id (^ExpressionBlock())(id, NSArray*, NSMutableDictionary*);
private:
NSExpression *expression;
};
id (^Foo::ExpressionBlock())(id, NSArray*, NSMutableDictionary*)
{
return [expression expressionBlock];
}
int main()
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
Foo a([NSExpression expressionForBlock:^id(id evaluatedObject, NSArray *expressions, NSMutableDictionary *context) {
return evaluatedObject;
} arguments:[NSArray arrayWithObject:#"Test"]]);
NSLog(#"%#", a.ExpressionBlock()(#"Hello", nil, nil));
[pool drain];
}
/usr/include/Block.h manipulates ObjC blocks using opaque void pointers, so that's probably what you should use to pass them around to C++ code if you can't compile it with a compiler supporting blocks. Also take note of the Block_copy and Block_release functions in that header. There's also an article on memory management of ObjC blocks.

Generating getters & setters in XCode

I am currently using xcode for some c++ development & I need to generate getters & setters.
The only way I know is generating getters & setters in Objective C style
something like this
- (string)name;
- (void)setName:(string)value;
I dont want this; I want c++ style generation with implementation & declaration for use in the header files.
Any idea...?
It sounds like you're just looking for a way to reduce the hassle of writing getters/setters (i.e. property/synthesize statements) all the time right?
There's a free macro you can use in XCode to even generate the #property and #synthesize statements automatically after highlighting a member variable that I find really helpful :)
If you're looking for a more robust tool, there's another paid tool called Accessorizer that you might want to check out.
Objective C != C++.
ObjectiveC gives you auto-implementation using the #property and #synthesize keywords (I am currently leaning ObjectiveC myself, just got a Mac!). C++ has nothing like that, so you simply need to write the functions yourself.
Foo.h
inline int GetBar( ) { return b; }
inline void SetBar( int b ) { _b = b; }
or
Foo.h
int GetBar( );
void SetBar( int b );
Foo.cpp
#include "Foo.h"
int Foo::GetBar( ) { return _b; }
void Foo::SetBar( int b ) { _b = b; }
something.h:
#interface something : NSObject
{
NSString *_sName; //local
}
#property (nonatomic, retain) NSString *sName;
#end
something.m :
#import "something.h"
#implementation something
#synthesize sName=_sName; //this does the set/get
-(id)init
{
...
self.sName = [[NSString alloc] init];
...
}
...
-(void)dealloc
{
[self.sName release];
}
#end