HowTo: Using C++ in Objective-C

Categories:Lab, Technology, Tutorial

When developing for iOS, a developer might sometimes need to go from Objective-C to C++ and from C++ to Objective-C again. For example when you have a library in C++ which you want to use inside your Objective-C project.
Both languages are derivatives from C but are somewhat a pain in the bottom to combine. So here’s a little how to on this subject.

Toolset.

For this example we will be working in XCode as it is the main tool for developing Objective-C applications.

What ?

We’ll be making a test project in which we will have an entry point in objective-C, then we will call a C++ class, which in turn will call an Objective-C class again through a C interface.

cpp2ObjC3


* I will not be going into learning code languages, you will have to put in the work yourself on this subject.



Pro Tip: Your Objective-C body files NEED to have the .mm extention.
This means our project will have c++ file going along with it. Normally when you create a class in XCode ( Obj-C ) the extension is .m . Just rename it so the extension is .mm

Let’s start.

Open XCode and create a standard project.


In this example we’ll have 5 main components:
- ViewController
- CPPCaller class ( obj-C )
- CPP class ( cpp )
- CInterface ( interface )
- ObjectiveC class which implements the CInterface.

1. ViewController

This will be our entry point from Objective-C.
From here we will call our Objective-C class “CPPCaller”.

#import "ViewController.h"
#import "CPPCaller.h"
 
@interface ViewController ()
@end
 
@implementation ViewController
 
- (void)viewDidLoad {  //main entry point for a viewcontroller.
	[super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
 
 
	// FLOW:
	// CPP caller (.mm) -> CPP (.cpp) -> ObjCClass (.mm)
 
	CPPCaller * caller = [[CPPCaller alloc] init];  // create the CPPCaller
	[caller Setup];					// call setup.
	[caller Start];					// call start
	[caller Stop];					// call stop
}
 
- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning];
	// Dispose of any resources that can be recreated.
}
 
@end


2. CPPCaller

This will be our Objective-C instance which will call our C++ class.

The header file ( CPPCaller.h ):

#ifndef CPPCaller_h
#define CPPCaller_h
 
#import <Foundation/Foundation.h>
 
//include .cpp header.
#if __cplusplus
	#include "CPP.h"
#endif
 
@interface CPPCaller : NSObject
@end
 
@interface CPPCaller()
 
-(id) init;
-(void) Setup;
-(void) Start;
-(void) Stop;
-(void) LOG: (NSString *) msg;
@end
 
#endif /* CPPCaller_h */

The body file ( CPPCaller.mm ):

#import <Foundation/Foundation.h>
 
#include "CPPCaller.h"  //include the objective-C CPPCaller header.
 
 
// here because this is an MM file.
@interface CPPCaller()
	@property (nonatomic) CPP * cppFile;   //include the CPP header.
@end
 
 
@implementation CPPCaller  //Begin CPPCaller body.
 
-(id) init {
	[self LOG:[NSString stringWithFormat:@"[CPP-CALLER] - Init"]]; //output a log statement.
	self = [super init];
	if(self){
 
		self.cppFile = new CPP(); //instantiate cpp;
		self.cppFile->init();	 // call "init" inside the cpp file.
	}
	return self;
}
 
-(void) Setup
{
	[self LOG:[NSString stringWithFormat:@"[CPP-CALLER] - Setup"]];  //output a log statement.
 
 
	//call cpp  setup.
	self.cppFile->Setup();  // call "Setup" inside the cpp file.
}
 
-(void) Start
{
	[self LOG:[NSString stringWithFormat:@"[CPP-CALLER] - Start"]]; //output a log statement.
 
	//call cpp.
	self.cppFile->Start(); // call "Start" inside the cpp file.
}
 
-(void) Stop
{
	[self LOG:[NSString stringWithFormat:@"[CPP-CALLER] - Stop"]];  //output a log statement.
 
	//call cpp.
	self.cppFile->Stop(); // call "Stop" inside the cpp file.
}
 
-(void) LOG:(NSString * ) msg   //method for quick logging.
{
	NSLog(msg);
}
@end


3. CPP

This will be our C++ file in which we will be calling an Objective-C class again.
This will be done through the CInterface,
so pay extra attention to the implementation of the CInterface.

The header file ( CPP.h ):

#ifndef CPP_h
#define CPP_h
 
#include <stdio.h>
#include <string>
#include <iostream>
 
class CInterface; // include the CInterface ( to get back to Objective-C )
 
class CPP
{
	public:
		CPP();
	   ~CPP();
 
		void init( void );
		void Setup( void );
		void Start( void );
		void Stop ( void );
 
	private:
		CInterface * _interface;
};
 
#endif /* CPP_h */

The body file ( CPP.cpp ):

#include <stdio.h>
 
#include "CPP.h"
#include "CInterface.h"
 
using namespace std;
 
CPP::CPP() : _interface( NULL )
{
	if(_interface == NULL)
		_interface = new CInterface();
 
};
 
CPP::~CPP( void )
{
	if(_interface)
	{
		delete _interface;
		_interface = NULL;
	}
};
 
void CPP::init( void )
{
	cout << "[CPP] - Init" << endl; // do a log statement for debug purposes.
 
	if(_interface != NULL){
		_interface->init();
	}
}
 
void CPP::Setup( void )
{
	cout << "[CPP] - Setup" << endl; // do a log statement for debug purposes.
 
	//call c interface.
	_interface->Setup();
 
};
 
void CPP::Start( void )
{
	 cout << "[CPP] - Start" << endl;
 
	//call c interface.
	_interface->Start();
};
 
void CPP::Stop( void )
{
	 cout << "[CPP] - Stop" << endl; // do a log statement for debug purposes.
 
	//call c interface
	_interface->Stop();
};


4. CInterface ( CInterface.h )

Will act as an intermediate interface between C++ and Objective-C.
Now this part is one to pay extra attention to. This will be an interface, thus it will be implemented inside a Objective-C class.
This will create an entry point for C++ to call, which in turn calls the Objective-C.
Because this is an interface we only define a header file.

#ifndef CInterface_h
#define CInterface_h
 
// !! Typedef the ObjCClass class
#if defined( __OBJC__ )
@class ObjCClass;
	typedef ObjCClass * T;
#else
	typedef void * T;
#endif
 
#ifdef __cplusplus //only when cplusplus
 
class CInterface
{
	public:
		 CInterface( void );
		~CInterface( void );
 
		void init ( void );
		void Setup( void );
		void Start( void );
		void Stop ( void );
 
	private:
		T self;
};
#endif // end ifdef cplusplus
#endif /* CInterface_h */

5. Implementing the CInterface

Now that we have our C++ interface done we can write the Obj-C class which will implement this interface.

The header file ( ObjCClass.h ):

#ifndef ObjCClass_h
#define ObjCClass_h
 
#import "CInterface.h"  //import the C interface header.
 
@interface ObjCClass : NSObject
 
//methods.
-(id) init;
-(void) Setup;
-(void) Start;
-(void) Stop;
 
@end
 
#endif /* ObjCClass_h */

The body file ( ObjCClass.mm ):

#import "ObjCClass.h"
 
@implementation ObjCClass
 
 
// !! C interface implementation.
CInterface::CInterface( void ): self( NULL)
{
 
}
CInterface::~CInterface( void )
{
 
}
void CInterface::init( void )
{
	self = [[ObjCClass alloc] init]; // instantiate the OBJCClass.
}
void CInterface::Setup( void )
{
	[(id) self Setup];			  // self is refferering to the ObjCClass.
}
void CInterface::Start( void )
{
	[(id) self Start];			 // self is refferering to the ObjCClass.
}
void CInterface::Stop( void )
{
	[(id) self Stop];			  // self is refferering to the ObjCClass.
}



As you can see, it is somewhat a puzzle to get this working correctly, but when you do… a whole new world will open and another hurdle will be out of your way.
Play around with it and try to implement your own functionality. The more you work with this structure the easier it will be to comprehend.

Hope this helps you on your way!
Happy coding.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

What is 8 + 12 ?
Please leave these two fields as-is:
IMPORTANT! To be able to proceed, you need to solve the following simple math (so we know that you are a human) :-)