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_helperdispose_helper 函数

构造 Block 结构体

  • 设置 isa_NSConcreteStackBlock 或是 _NSConcreteGlobalBlock (如果是静态或是文件级别的 Block)
  • 根据上下文设置对应的 flags

引入变量

  • 引入 常量变量 时,直接在 Block_literal 中引入对应的 常量变量,如果变量是 Block,同时需要初始化对应的 copy_helperdispose_helper
  • 引入 __block variable 时,需要在 Block_literal 中引入对应变量和 forwarding 指针指向 Block_literal,同时访问 __block variable 时通过 self->forwarding->capture_varible 进行。这样,当 stack 上的 Block 被拷贝至 heap 上时,stack->forwarding = heap,使得无论是调用 stack 还是 heap 上的 Block 都能够访问统一的变量。