block 之 block的底层实现

作者: 欣东 | 来源:发表于2016-05-15 17:09 被阅读311次

    前言

    最近在总结关于block的东西,可能会写几篇关于block的博客,语法那些就不说,这里提供一个语法的入口,我们主要探究block的底层实现、block引用局部变量、block的内存管理,今天先讲下block的底层实现。

    block实例

    #import <Foundation/Foundation.h>
    
    void hello_(){
        int i = 2;
        int j = 3;
        long (^myBlock)(void) = ^long(){
            return i*j*10;
        };
    }
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            
     
        }
        return 0;
    }
    

    定义hello方法是方便我们等下查看编译代码的时候准确定位myBlock的实现。用clang将objected-C 代码编译为C++代码。

    控制台命令:clang -rewrite-objc main.m 
    

    我们打开main.cpp文件,定位到以下代码:

    struct __block_impl {
      void *isa;
      int Flags;
      int Reserved;
      void *FuncPtr;
    };
    

    这是block基类的定义,所有block都继承于它,拥有它以下那些属性:
    isa是指向该block的类型的类,也就是我们理解的对象指针;
    Flags包含了引用计数;
    Reserved:保留变量,我的理解是表示block内部的变量数;
    FuncPtr:函数指针,指向具体block实现的函数的调用地址;

    struct __hello__block_impl_0 {
      struct __block_impl impl;
      struct __hello__block_desc_0* Desc;
      int i;
      int j;
      __hello__block_impl_0(void *fp, struct __hello__block_desc_0 *desc, int _i, int _j, int flags=0) : i(_i), j(_j) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    

    这是myBlock的定义,它的结构体以hello打头,代表myBlock位于hello函数里,这是block的命名方式。__hello__block_desc_0指的是myBlock的描述。

    static long __hello__block_func_0(struct __hello__block_impl_0 *__cself) {
      int i = __cself->i; // bound by copy
      int j = __cself->j; // bound by copy
    
            return i*j*10;
        }
    

    myBlock内函数的具体实现,注意bound by copy,block对外部引用变量做只读拷贝,还有另外的一种情况,在以后讲到关于block引用局部变量的时候会说。

    static struct __hello__block_desc_0 {
      size_t reserved;
      size_t Block_size;
    } __hello__block_desc_0_DATA = { 0, sizeof(struct __hello__block_impl_0)};
    

    这是myBlock的具体描述

    void hello_(){
        int i = 2;
        int j = 3;
        long (*myBlock)(void) = ((long (*)())&__hello__block_impl_0((void *)__hello__block_func_0, &__hello__block_desc_0_DATA, i, j));
    }
    

    myBlock实例变量的定义

    做下小小总结

    block是对象;
    编译器会根据block捕获的局部变量,生成具体的结构体定义。block内部的代码将会提取出来,成为一个单独的C函数(eg:__hello__block_func_0)。创建block时,实际就是在方法中声明一个struct,并且初始化该struct的成员。而执行block时,就是调用那个单独的C函数,并把该struct指针传递过去;
    block中包含了被引用的局部变量(由struct持有),也包含了控制成分的代码块(由函数指针持有),符合闭包(closure)的概念。

    相关文章

      网友评论

        本文标题:block 之 block的底层实现

        本文链接:https://www.haomeiwen.com/subject/kibvrttx.html