前段时间心血来潮,研究了一下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:欢迎大家勘误,共同学习!)