从Objective-C调用C ++

对于那些已经成功地从Objective-C中调用C ++代码的人,请给我一些启发。

这个链接说你需要使用他在文章中描述的技术来包装你的C ++代码。 它看起来不错,但我仍然有问题。

这个链接指出,只要调用C ++类的Objective-C类已经被转换为.mm(Objective-C ++)类,那么这两者应该很好地结合在一起。

每当我尝试添加方法调用时,这些方法中的每一个都使我感到悲伤。 有人可以给我一个简单的Hello World iOS应用程序的代码,这个应用程序使用Objective-C作为“Hello”部分,而C ++类作为“World”作为中间部分使用Objective-C ++类。 或者我仍然有整个概念错误?

本质上你需要一个带有.mm扩展名的ObjC类,它用.mm扩展名来调用一个ObjC类。 第二个将被用作C ++包装类。 包装类将调用您的实际.cpp类。 这有点棘手,所以我会给你一些详细的代码。 以下是该项目的概述:

在这里输入图像说明

在你的ObjC代码(ViewController)中,你可以调用CplusplusMMClass

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

这是CplusplusMMClass .h和.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 

这是WrapperClass .h和.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 

这里是PureCplusplusClass .h和.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; } 

这个代码不完美! 我遇到名字空间testing被识别的麻烦。 我会尽快更新。

但是,这应该让你在那里!

另一个(做作):

使用一个C ++类作为伊娃:

文件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 

注意:

可执行文件可能需要显式链接到C ++库,例如通过向“其他链接器标志”添加一个附加标志: -lc++

或者, main.m文件可以重命名为main.mm

后者在select“正确的”库方面更加强大,因为工具链本身就是这样做的。 但也许,对于审查这个项目的其他人来说,重命名的“main.m”可能并不那么明显,可能会引起混淆。

按照要求; 一个例子:

 #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