动手点关注 干货不迷路 👆
背景
苹果的 Objective-C 编译器允许用户在同一个源文件里自由地混合使用 C++和 Objective-C,混编后的语言叫 Objective-C++。相对于其它语言(例如 Swift、Kotlin、Dart 等)和 C++的文件隔离和架桥通信(例如 Kotlin 使用JNI,Dart 使用FFI),Objective-C 和 C++的同文件混编方式无疑是令人舒畅的。OC/C++混编虽然可以在一个文件中进行编写,但是有一些注意事项需要了解:Objective-C++没有为 OC 类增加 C++的功能,也没有为 C++增加 OC 的功能,例如:不能用 OC 语法调用 C++对象,也不能为 OC 对象增加构造函数和析构函数,也不能将this和self互相替换使用。类的体系结构是独立的,C++类不能继承 OC 类,OC 类也不能继承 C++类。
本文主要就之前令人困惑的 OC 的Block和 C++的lambda混编问题做一些探索。
实验环境:C++版本为 C++14,OC 只局限于 ARC。
基本了解
在深入探索之前,先通过对比的方式了解下二者:
语法
^(int x, NSString *y){} // ObjC, take int and NSString*
[](int x, std::string y){} // C++, take int and std::string
^{ return 42; } // ObjC, returns int
[]{ return 42; } // C++, returns int
^int { if(something) return 42; else return 43; }
[]()->int { if(something) return 42; else return 43; }
原理
OC 的Block的底层可以参考《深入研究 Block 捕获外部变量和 __block 实现原理》(https://halfrost.com/ios_block/),这里不做深入探究,仅仅是要展开代码达到对比效果。
- (void)viewDidLoad {
[super viewDidLoad];
int x = 3;
void(^block)(int) = ^(int a) {
NSLog(@"%d", x);
};
block(5);
}
通过clang -rewrite-objc重写,可以得到以下结果:
struct __ViewController__viewDidLoad_block_impl_0 {
struct __block_impl impl;
struct __ViewController__viewDidLoad_block_desc_0* Desc;
int x;
__ViewController__viewDidLoad_block_impl_0(void *fp, struct __ViewController__viewDidLoad_block_desc_0 *desc, int _x, int flags=0) : x(_x) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __ViewController__viewDidLoad_block_func_0(struct __ViewController__viewDidLoad_block_impl_0 *__cself, int a) {
int x = __cself->x; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_st_jhg68rvj7sj064ft0rznckfh0000gn_T_ViewController_d02516_mii_0, x);
}
static struct __ViewController__viewDidLoad_block_desc_0 {
size_t reserved;
size_t Block_size;
} __ViewController__viewDidLoad_block_desc_0_DATA = { 0, sizeof(struct __ViewController__viewDidLoad_block_impl_0)};
static void _I_ViewController_viewDidLoad(ViewController * self, SEL _cmd) {
((void (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("ViewController"))}, sel_registerName("viewDidLoad"));
int x = 3;
void(*block)(int) = ((void (*)(int))&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA, x));
((void (*)(__block_impl *, int))((__block_impl *)block)->FuncPtr)((__block_impl *)block, 5);
}
而 C++ lambda采取了截然不同的的实现机制,会把lambda表达式转换为一个匿名 C++类。这里借助cppinsights 看下 C++ lambda的实现。
#include <cstdio>
struct A {
int x;
int y;
};
int main()
{
A a = {1, 2};
int m = 3;
auto add = [&a, m](int n)->int {
return m + n + a.x + a.y;
};
m = 30;
add(20);
}
#include <cstdio>
struct A
{
int x;
int y;
};
int main()
{
A a = {1, 2};
int m = 3;
class __lambda_12_15
{
&nb

最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



