[英]Calling C++ from Objective-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;
}
这段代码并不完美! 我在识别名称空间测试时遇到问题。 我会在可以的时候更新。
根据要求; 一个例子:
#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
另一个(人为的):
使用 C++ 类作为 ivar:
文件 Foo.h
#import <Foundation/Foundation.h>
@interface Foo : NSObject
@property (nonatomic, readonly) NSString* what;
@end
文件: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
。
后者在选择“正确”库时更加稳健,因为工具链会自行完成。 但也许,对于其他检查项目的人来说,重命名的“main.m”可能不是那么明显,可能会引起混淆。
我在 xcode 12.4 中遇到了这种情况,需要在 Objective-c 项目中使用现有的 C++ 类“CppModule”。 这是我所做的。
#if defined __cplusplus declarations #endif
#include <string> using namespace std;
在 module.h 文件中包含 C++ 头文件:
#include < CppModule.hpp>
static CppModule *module_cpp;
module_cpp = new CppModule(parameters);
并且 C++ 模块仍然可以通过该静态 module_cpp * 指针访问。
CppModule::Result r = module_cpp->CppMethod();
似乎工作得很好!
如果有人能解释 4 中的奇怪之处,我将不胜感激。
我需要的模块只是做一些复杂的(数字)计算,我不想将代码转换为 Objective-C。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.