Block的本質(zhì)
Block轉(zhuǎn)換為C++
這樣一段代碼
int main(int argc, const char * argv[]) {
void (^blk)(void) = ^{
printf("Block");
};
blk();
return 0;
}
經(jīng)過clang轉(zhuǎn)換為c++代碼之后
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
printf("Block");
}
int main(int argc, const char * argv[]) {
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *)) ((__block_impl *)blk)->FuncPtr) ((__block_impl *)blk);
return 0;
}
將代碼拆開來看
OC中定義一個(gè)Block
void (^blk)(void) = ^{
printf("Block");
};
轉(zhuǎn)換成了下面的代碼田炭。
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
去掉類型轉(zhuǎn)換勇边,將代碼簡(jiǎn)化
void(*blk)(void) = __main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA)
從上面可以看到兽掰,=
后面是創(chuàng)建一個(gè)Block的部分,轉(zhuǎn)換之后創(chuàng)建Block的過程其實(shí)就是調(diào)用了__main_block_impl_0
結(jié)構(gòu)體的構(gòu)造方法生成一個(gè)結(jié)構(gòu)體的實(shí)例过蹂。
這個(gè)構(gòu)造方法中傳入了兩個(gè)參數(shù)纠吴。第一個(gè)是__main_block_func_0
硬鞍,從上面的代碼可以看到,這是一個(gè)函數(shù)指針戴已。這個(gè)函數(shù)就是Block的具體實(shí)現(xiàn)轉(zhuǎn)換成的函數(shù)固该。第二個(gè)參數(shù)是一個(gè)結(jié)構(gòu)體實(shí)例的指針。這個(gè)參數(shù)是確定了結(jié)構(gòu)體所需要的空間大小糖儡。
通過上面分析可以看到伐坏,定義一個(gè)block本質(zhì)是定義了一個(gè)結(jié)構(gòu)體實(shí)例。
接下來看=
左邊的部分握联。
=
左邊定義了一個(gè)Block類型的blk
變量桦沉。從上面可以看到右邊是調(diào)用了結(jié)構(gòu)體的構(gòu)造函數(shù),那么自然生成的是結(jié)構(gòu)體的實(shí)例金闽,所以Block類型的變量其實(shí)也就是一個(gè)結(jié)構(gòu)體的指針纯露。void(^blk)(void)
== struct __main_block_impl_0 *blk
block對(duì)象轉(zhuǎn)換為c++之后其實(shí)就是一個(gè)結(jié)構(gòu)體實(shí)例,block變量就是一個(gè)結(jié)構(gòu)體實(shí)例的指針
解析__main_block_impl_0
結(jié)構(gòu)體
既然Block就是一個(gè)__main_block_impl_0
的實(shí)例代芜,那么看看這個(gè)結(jié)構(gòu)體的具體內(nèi)容
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
這個(gè)結(jié)構(gòu)體有兩個(gè)屬性和一個(gè)構(gòu)造方法埠褪,去掉構(gòu)造方法之后,這個(gè)結(jié)構(gòu)體就只有兩個(gè)屬性。
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
};
第一個(gè)屬性是一個(gè)結(jié)構(gòu)體钞速,這個(gè)結(jié)構(gòu)體的聲明如下
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
這個(gè)結(jié)構(gòu)體定義了一個(gè)函數(shù)指針的屬性贷掖,這個(gè)指針指向了block實(shí)現(xiàn)轉(zhuǎn)換后的函數(shù)。
還有一個(gè)isa指針渴语。用于指向該block所屬的類型