前段时间心血来潮,研究了一下block底层实现,在网上看了好多文章,基本都是通过clang 将代码转换为C++代码去分析Blcok的实现。今天我们反过来思考,用C去实现一个OC Block的效果。
Block的实现本质上是一些结构体,函数指针,函数,的综合运用。
话不多说,直奔主题:
Block的实现,首先需要声明一个结构,这个结构是我们实现Block的基础,也是关键1
2
3
4
5
6
7
8
9
10
11struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
说明一下:
1.isa 保存的是Block的类型
2.Flags 当block发生copy时,会用到
3.FuncPtr 指针,指向block内的函数实现(后面函数指针调用的函数)
这个结构体,是所有类型的Block都会有的一部分。
然后我们看第二个结构体1
2
3
4
5
6
7static 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实现最重要的结构,声明如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19struct __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函数:1
2
3
4
5static void __simpleblk_block_func_0(struct __simpleblk_block_impl_0 *__cself) {
printf("this is charles's simple block!!");
}
这个函数其实就是我们的Block块里面的操作。后面调用之后就会很清楚。
到这里我们就可以写一个C函数来达到一个Block的效果:
int simpleblk(){
//声明一个结构体变量1
__simpleblk_block_impl_0 __simpleblk_impl0 = __simpleblk_block_impl_0((void *)__simpleblk_block_func_0,&__simpleblk_block_desc_0_DATA);
//声明一个函数指针变量block,并且将上面的结构体变量的地址付给block指针1
void(*block)(void) = (void(*)())&__simpleblk_impl0;
1 | /* |
1 | ((void (*)(struct __block_impl *))((struct __block_impl *)block)->FuncPtr)((struct __block_impl *)block); |
其实,上面写了这么多,换成OC代码其实就是在一个函数里面,声明了一个Block变量并且调用它。1
2
3
4
5
6
7
8
9
10
11
12
13int simpleblk() {
void (^block)(void) = ^(){
printf("this is charles's block!!");
};
block();
return 1;
}
到这里我们用C语言实现OC的 Block效果基本就写完了,不知道各位看官是否看明白了呢。。(PS:欢迎大家勘误,共同学习!)