Calling C++ from Objective-C

For those of you who have successfully been able to call C++ code from Objective-C, will you please enlighten me?

This link says you need to wrap your C++ code using a technique he describes in his article. It looks good but I still have problems.

  • How to know if a UITextField in iOS has blank spaces
  • iOS update to 10.3.1 breaks HTML input element
  • duplicate symbols for architecture arm64 after xCode 8.0 update
  • Error creating REST request with Swift to Google app engine endpoint
  • How can I know users click fast forward and fast rewind buttons on the playback controls in iPhone
  • How can I scan barcodes on iOS?
  • This link says that as long as the Objective-C class calling the C++ class has been converted to a .mm (Objective-C++) class then the two should work nicely together.

    Each of these approaches are causing me grief the minute I try to add a method call. Can somebody please give me code for a simple Hello World iOS app that uses Objective-C for the “Hello” part and a C++ class for the “World” part with an Objective-C++ class in the middle? Or do I still have the entire concept wrong?

    3 Solutions Collect From Internet About “Calling C++ from Objective-C”

    Essentially you need an ObjC class with .mm extension that calls an ObjC class with .mm extension. The second one will be used as a C++ wrapper class. The wrapper class will call your actual .cpp class. It’s a little tricky, so I’m going to give you some verbose code. Here is an overview of the project:

    enter image description here

    In your ObjC code (ViewController) you would call the CplusplusMMClass

    - (IBAction)buttonPushed:(UIButton *)sender {
        self.mmclass = [[CplusplusMMClass alloc]init];  // bad practice; but showing code
        NSString *str = [self.mmclass fetchStringFromCplusplus];
        [self populateLabel:str];
    }
    

    Here is the CplusplusMMClass .h and .mm

    #import <Foundation/Foundation.h>
    #import "WrapperClass.h"
    
    @interface CplusplusMMClass : NSObject
    @end
    
    @interface CplusplusMMClass()
    @property (nonatomic, strong) WrapperClass *wrapper;
    - (NSString*)fetchStringFromCplusplus;
    @end
    

    #import "CplusplusMMClass.h"
    #import "WrapperClass.h"
    
    @implementation CplusplusMMClass
    
    - (NSString*)fetchStringFromCplusplus {
        self.wrapper = [[WrapperClass alloc] init];
        NSString * result = [self.wrapper getHelloString];
        return result;
    }
    
    @end
    

    Here is WrapperClass .h and .mm

    #ifndef HEADERFILE_H
    #define HEADERFILE_H
    
    #import <Foundation/Foundation.h>
    
    #if __cplusplus
    
    #include "PureCplusplusClass.h"
    
    @interface WrapperClass : NSObject
    @end
    
    @interface WrapperClass ()
    - (NSString *)getHelloString;
    @end
    
    
    #endif
    #endif
    

    #import "WrapperClass.h"
    
    #include "WrapperClass.h"
    #include "PureCplusplusClass.h"
    
    using namespace test;
    
    @interface WrapperClass ()
    @property (nonatomic) HelloTest helloTest;
    @end
    
    @implementation WrapperClass
    
    - (NSString *)getHelloString {
        self.helloTest = *(new HelloTest);
        std::string str = self.helloTest.getHelloString();
        NSString* result = [[NSString alloc] initWithUTF8String:str.c_str()];
        return result;
    }
    
    @end
    

    Here is the PureCplusplusClass .h and .cpp

    #ifndef __HelloWorld__PureCplusplusClass__
    #define __HelloWorld__PureCplusplusClass__
    
    #include <stdio.h>
    #include <string>
    
    using namespace std;
    
    namespace test {
        class HelloTest
        {
        public:
            std::string getHelloString();
        };
    }
    
    #endif /* defined(__HelloWorld__PureCplusplusClass__) */
    

    #include <stdio.h>
    #include <string>
    
    std::string test::HelloTest::getHelloString() {
        std::string outString = "Hello World";
        return outString;
    }
    

    This code is not perfect! I’m having trouble with the namespace test being recognized. I’ll update when I can.

    But this should get you there!!!!

    Another (contrived) one:

    Use a C++ class as an ivar:

    File Foo.h

    #import <Foundation/Foundation.h> 
    
    @interface Foo : NSObject
    @property (nonatomic, readonly) NSString* what;
    @end
    

    File: Foo.mm

    #import "Foo.h"
    #include <string>
    
    @implementation Foo {
        std::string _string;  // C++ class must have a default c-tor
    }
    
    - (id)init
    {
        self = [super init];
        if (self) {
            _string = "Hello, World!"
        }
        return self;
    }
    
    - (NSString*) what {
        NSString* result = [[NSString alloc] initWithBytes:_string.data()
                                                    length:_string.size() 
                                                  encoding:NSUTF8StringEncoding];
        return result;
    }
    
    @end
    

    Note:

    An executable may need to explicitly link against the C++ library, e.g. by adding an additional flag to “Other Linker Flags”: -lc++

    Alternatively, the main.m file can be renamed to main.mm.

    The latter is more robust in selecting the “correct” library, since the tool chain will do that itself. But perhaps, for anyone else examining the project, a renamed “main.m” may not be that obvious and may cause confusion.

    As requested; an example:

    #import <Foundation/Foundation.h>
    #import <vector>
    #import <string>
    
    int main(int argc, const char **argv) {
        std::vector<std::string> v;
        v.push_back("Hello");
        v.push_back("World");
        for (std::string s : v)
            NSLog(@"%s", s.c_str());
        return 0;
    }
    
    $ clang -std=c++11 -stdlib=libc++ -o callcpp callcpp.mm -framework Foundation -lc++
    $ ./callcpp
    2013-10-07 17:16:13.725 callcpp[37710:707] Hello
    2013-10-07 17:16:13.726 callcpp[37710:707] World