iOS Block ABI - xiangwangfeng/xiangwangfeng.github.io GitHub Wiki
iOS Block ABI
参考内容
Block Implementation Specfication
基础 ABI
struct Block_literal_1 {
void *isa; // initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor_1 {
unsigned long int reserved; // NULL
unsigned long int size; // sizeof(struct Block_literal_1)
// optional helper functions
void (*copy_helper)(void *dst, void *src); // IFF (1<<25)
void (*dispose_helper)(void *src); // IFF (1<<25)
// required ABI.2010.3.16
const char *signature; // IFF (1<<30)
} *descriptor;
// imported variables
};
isa
用于包装Block
为对象直接使用flags
标示字段 (下面为主要的几个标示)BLOCK_HAS_COPY_DISPOSE
是否需要拷贝/销毁 (1 << 25)BLOCK_HAS_CTOR
是否有C++
代码 (1 << 26)
reserved
保留字段invoke
执行函数,参入参数为Block_literal
指针和可能的参数列表descriptor
描述信息reversed
保留字段size
Block
结构体大小copy_helper
拷贝函数,当flags
包含BLOCK_HAS_COPY_DISPOSE
时有dispose_helper
销毁函数,当flags
包含BLOCK_HAS_COPY_DISPOSE
时有signature
签名信息
初始化
当一个 Block
在栈上被创建时,有如下流程
构造描述信息 (descriptor)
- 构造执行函数
invoke
,接受Block
结构体作为第一参数以及其他参数列表 - 将
Block_literal
大小信息赋值为descriptor.size
- 如果有需要添加
copy_helper
和dispose_helper
函数
构造 Block 结构体
- 设置
isa
为_NSConcreteStackBlock
或是_NSConcreteGlobalBlock
(如果是静态或是文件级别的Block
) - 根据上下文设置对应的
flags
引入变量
- 引入
常量变量
时,直接在Block_literal
中引入对应的常量变量
,如果变量是Block
,同时需要初始化对应的copy_helper
和dispose_helper
- 引入
__block variable
时,需要在Block_literal
中引入对应变量和forwarding
指针指向Block_literal
,同时访问__block variable
时通过self->forwarding->capture_varible
进行。这样,当stack
上的Block
被拷贝至heap
上时,stack->forwarding = heap
,使得无论是调用stack
还是heap
上的Block
都能够访问统一的变量。