Script.it .Nam Myoho Renghe Kyo.

Script.it
[iOS] Using C++ in Objective-C

When developing for iOS a developer might sometimes need to go from Objective-C to C++ and from C++ to Objective-C again.
Both languages are derrivatives from C but are somewhat a pain in the ass 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 thru 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 extention is .m . Just rename it so the extention is .mm
obj-c-and-cpp



Let’s start.
1. 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”.

?View Code OBJECTIVE-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#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:

?View Code OBJECTIVE-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#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:

?View Code OBJECTIVE-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#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.

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#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:

?View Code OBJECTIVE-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#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:

?View Code OBJECTIVE-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#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 comprehand.

Hope this helps you on your way!
Happy coding.

\o
Rackdoll

Creative Commons License
[iOS] Using C++ in Objective-C by Script.it, unless otherwise expressly stated, is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Netherlands License.

Comments are closed.

Categories
Archives
Live Supporters