开发者社区> 问答> 正文

block的内部实现,结构体是什么样的?

block的内部实现,结构体是什么样的?

展开
收起
montos 2020-04-13 20:52:43 1587 0
1 条回答
写回答
取消 提交回答
  • block的结构体如下:

    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也是一个对象类型,具体类型包括_NSConcreteGlobalBlock、_NSConcreteStackBlock、_NSConcreteMallocBlock。

    flags:block 的负载信息(引用计数和类型信息),按位存储,也可以获取block版本兼容的相关信息。以下是flags按bit位取与的所有可能值:

    enum {
        // Set to true on blocks that have captures (and thus are not true
        // global blocks) but are known not to escape for various other
        // reasons. For backward compatibility with old runtimes, whenever
        // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a
        // non-escaping block returns the original block and releasing such a
        // block is a no-op, which is exactly how global blocks are handled.
        BLOCK_IS_NOESCAPE      =  (1 << 23),
    
        BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
        BLOCK_HAS_CTOR =          (1 << 26), // helpers have C++ code
        BLOCK_IS_GLOBAL =         (1 << 28),
        BLOCK_HAS_STRET =         (1 << 29), // IFF BLOCK_HAS_SIGNATURE
        BLOCK_HAS_SIGNATURE =     (1 << 30),
    };
    
    switch (flags & (3<<29)) {
      case (0<<29):      10.6.ABI, no signature field available
      case (1<<29):      10.6.ABI, no signature field available
      case (2<<29): ABI.2010.3.16, regular calling convention, presence of signature field
      case (3<<29): ABI.2010.3.16, stret calling convention, presence of signature field,
    }
    

    由此可知:当flags & (3<<29) is BLOCK_HAS_COPY_DISPOSE的时候,才会有copy_helper和dispose_helper函数指针。

    invoke:是block具体实现函数指针地址,可以通过此地址直接调用block。

    Block_descriptor_1:block的描述文内容,它包括如下:

    size:block所占的内存大小

    copy_helper:copy函数指针(不同版本不一定存在)

    dispose_helper:dispose函数指针(不同版本不一定存在)

    signature:block的实现函数的签名(不同版本不一定存在),可以通过此指针获取block的参数内容描述、返回值内容描述等

    获取block的方法签名,可以参考这篇文章

    2020-04-13 20:52:56
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载