美文网首页
Block底层实现之逆向思维

Block底层实现之逆向思维

作者: 潭清 | 来源:发表于2017-06-06 17:28 被阅读22次

    前段时间心血来潮,研究了一下block底层实现,在网上看了好多文章,基本都是通过clang 将代码转换为C++代码去分析Blcok的实现。今天我们反过来思考,用C去实现一个OC Block的效果。

    Block的实现本质上是一些结构体,函数指针,函数,的综合运用。

    话不多说,直奔主题:

    Block的实现,首先需要声明一个结构,这个结构是我们实现Block的基础,也是关键

    struct __block_impl {

    void *isa; 

    int Flags;

    int Reserved;

    void *FuncPtr;

    };

    说明一下:

    1.isa 保存的是Block的类型

    2.Flags 当block发生copy时,会用到

    3.FuncPtr 指针,指向block内的函数实现(后面函数指针调用的函数)

    这个结构体,是所有类型的Block都会有的一部分。

    然后我们看第二个结构体

    static struct __simpleblk_block_desc_0 {

    size_t reserved;

    size_t Block_size;

    } __simpleblk_block_desc_0_DATA = {0,sizeof(struct __simpleblk_block_impl_0)};

    说明一下:

    1.reserved 保留字段默认是0

    2.Block_size  用来保存block所占内存大小。

    这个结构体用来描述block的大小等信息,__simpleblk_block_desc_0_DATA是__simpleblk_block_desc_0的一个结构体实例。

    我们再看第三个结构体,也是Block实现最重要的结构,声明如下:

    struct __simpleblk_block_impl_0 {

    struct __block_impl impl;

    struct __simpleblk_block_desc_0 *Desc;

    __simpleblk_block_impl_0(void *fp,struct __simpleblk_block_desc_0 *desc,int flags = 0){

    impl.isa = &_NSConcreteStackBlock;

    impl.Flags = flags;

    impl.FuncPtr = fp;

    Desc = desc;

    }

    };

    说明一下:

    从这个结构中可以看到,该结构体含有 __block_impl 结构的变量 和 __simpleblk_block_desc_0 结构的变量,以及结构体构造函数__simpleblk_block_impl_0,结构体构造函数用来初始化变量__block_impl和__simpleblk_block_desc_0。

    到这里,我们实现最简单的Block所需要的结构就声明完了,但是要达到OC Block 那种效果,仅有结构体 肯定是不够的。截下来我们来看一个关键的函数,你没猜错就是一个很简单的C函数:

    static void __simpleblk_block_func_0(struct __simpleblk_block_impl_0 *__cself) {

    printf("this is charles's simple block!!");

    }

    这个函数其实就是我们的Block块里面的操作。后面调用之后就会很清楚。

    到这里我们就可以写一个C函数来达到一个Block的效果:

    int simpleblk(){

    //声明一个结构体变量

    __simpleblk_block_impl_0 __simpleblk_impl0 = __simpleblk_block_impl_0((void *)__simpleblk_block_func_0,&__simpleblk_block_desc_0_DATA);

    //声明一个函数指针变量block,并且将上面的结构体变量的地址付给block指针

    void(*block)(void) = (void(*)())&__simpleblk_impl0;

    /*

    下面这句代码 实际上调用的是 __simpleblk_block_func_0()函数

    就是函数指针调用函数。

    */

    ((void (*)(struct __block_impl *))((struct __block_impl *)block)->FuncPtr)((struct __block_impl *)block);

    return 1;

    }

    其实,上面写了这么多,换成OC代码其实就是在一个函数里面,声明了一个Block变量并且调用它。

    int simpleblk() {

    void (^block)(void) = ^(){

    printf("this is charles's block!!");

    };

    block();

    return 1;

    }

    到这里我们用C语言实现OC的 Block效果基本就写完了,不知道各位看官是否看明白了呢。。(PS:欢迎大家勘误,共同学习!)

    相关文章

      网友评论

          本文标题:Block底层实现之逆向思维

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