前言
最近在研究 Cronet
网络库,涉及到 Android
和 iOS
,由于对 OC
不怎么熟悉,所以在使用的时候碰到了 C++
与 OC
互相调用的问题,于是便有了此文。
字符串转换
1
2
3
4
5
6
|
// NSString -> std::string
NSString* str = @"oc string";
std::string s = std::string([str UTF8String]);
// std::string -> NSString
NSString* nstr = [NSString stringWithCString: str.c_str() encoding: [NSString defaultCStringEncoding]];
|
C++ 调用 OC Block
由于 .cpp
文件无法识别 OC
的代码, .m
文件无法识别 C++
的代码,所以这两者之间相互调用需要写在 .mm
的文件中,这样编译器才能识别。
C++
的代码要写在 .mm
文件中,因为在 .h
中 OC
无法识别 class
关键字
来看一个例子,先定义一个头文件 InvokeBlock.h
1
2
3
4
5
6
7
8
9
10
11
|
#import <Foundation/Foundation.h>
// 定义一个OC Block
typedef void(^OCBlock)();
@interface Ocpp : NSObject
// 申明一个 OC 的初始化方法,用于传递 Block
+ (void) InitBlock: (OCBlock)block;
@end
|
导入 OC
的头文件要使用 #import
, C++
的可以使用 #include
这里要注意 C++ 和 OC 混编一定要 .mm
的后缀,这样才能被识别。
定义 InvokeBlock.mm
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
|
#import "InvokeBlock.h"
class InvokeBlock {
public:
InvokeBlock(OCBlock block) : block_(block) {}
// 调用 Block
void invoke() {
block_();
}
private:
// 保存Block
__strong OCBlock block_;
};
@implementation Ocpp
// 定义 InitBlock,创建 InvokeBlock,并把block 传进去
+ (void)InitBlock: (OCBlock)block{
InvokeBlock* invokeBlock = new InvokeBlock(block);
invokeBlock->invoke(); // 调用invoke用于回调block
delete invokeBlock; // 用完释放
}
@end
|
C++
的代码要写在 .mm
中,不能写在头文件中,不然会报错。估计是识别不了。
接着就可以在 ViewController.m
中使用了
1
2
3
4
5
6
|
- (void)viewDidLoad {
[super viewDidLoad];
[Ocpp InitBlock:^{
NSLog(@"block invoke from c++");
}];
}
|
执行之后控制台就打印了 block invok from c++
。
参考