0%

从Block源码看其实现

在堆上生成的Block

创建Block

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>
int main()
{
void (^Block)(void) = ^{
printf("Block\n");
};
return 0;
}

经过clang编译后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

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

struct {
struct __block_impl impl;
struct __main_block_desc_0* Desc;

// 构造函数初始化__main_block_impl_0
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteStackBlock; // _NSConcreteStackBlock用于初始化__block_impl结构体的isa成员
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}

};
// 方法__main_block_func_0传入的是__main_block_impl_0结构体指针
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

NSLog((NSString *)&__NSConstantStringImpl__var_folders_dp_q1vmhmws4zvd8s8jq5q8f37c0000gn_T_block_5bf957_mi_0);
}

// 描述,
static struct __main_block_desc_0 {
size_t reserved; // 今后版本升级所需的区域
size_t Block_size; // Block的大小
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};


int main(int argc, char const *argv[])
{
// 转换后,变成了__main_block_func_0,其规则是:__Block语法所在的函数名_block_func_block语法在函数中出现的顺序
// void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));

// 去掉转换后
// 将__main_block_impl_0结构体类型的自动变量,既栈上生成的__main_block_impl_0结构体实例指针,赋值给__main_block_impl_0结构体指针类型的block
struct __main_block_impl_0 tmp = __main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
struct __main_block_impl_0 *block = &tmp;
||
// 对应以下最初识代码
void (^block)(void) = ^{
printf("Block\n");
};

// ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
// 去掉转换后
(*block -> __block_impl.FuncPtr)(block);

return 0;
}

分配在数据区的全局Block

创建OC的Block原码:

1
2
3
4
5
6
7
8
9
#import <Foundation/Foundation.h>
// 全局Block
void (^blk)(void) = ^{
printf("Global Block\n");
};
int main(int argc, char const *argv[])
{
return 0;
}

用clang命令编译该文件

1
clang -rewrite-objc -fobjc-arc blk.m

得到如下源码(删除辅助代码后)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};

struct __blk_block_impl_0 {
struct __block_impl impl;
struct __blk_block_desc_0* Desc;
__blk_block_impl_0(void *fp, struct __blk_block_desc_0 *desc, int flags=0) {
impl.isa = &_NSConcreteGlobalBlock; // 分配在数据区的全局Block
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __blk_block_func_0(struct __blk_block_impl_0 *__cself) {

printf("Global Block\n");
}

static struct __blk_block_desc_0 {
size_t reserved;
size_t Block_size;
} __blk_block_desc_0_DATA = { 0, sizeof(struct __blk_block_impl_0)};
static __blk_block_impl_0 __global_blk_block_impl_0((void *)__blk_block_func_0, &__blk_block_desc_0_DATA);
void (*blk)(void) = ((void (*)())&__global_blk_block_impl_0);

int main(int argc, char const *argv[])
{
return 0;
}

Block自动截获变量

源码

1
2
3
4
5
6
7
8
9
10
11
#import <Foundation/Foundation.h>

int main(int argc, char const *argv[])
{
int a = 1;
const char *fmt = "1";
void (^blk)(void) = ^{
printf("%d %s\n", a, fmt);
};
return 0;
}

编译后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
// 使用自动变量被当做成员变量追加到__main_block_impl_0结构体中
int a;
const char *fmt;

__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, const char *_fmt, int flags=0) : a(_a), fmt(_fmt) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int a = __cself->a; // bound by copy
const char *fmt = __cself->fmt; // bound by copy

printf("%d %s\n", a, fmt);
}

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)};

int main(int argc, char const *argv[])
{
int a = 1;
const char *fmt = "1";
void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, a, fmt));
return 0;
}

Block修改静态变量:全局变量的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import <Foundation/Foundation.h>

int global_val = 1; // 全局变量
static int static_global_val = 2; // 静态全局变量

int main(int argc, char const *argv[])
{
static int static_val = 3;// 静态局部变量

void (^blk)(void) = ^{
global_val ++;
static_global_val ++;
static_val ++;
};
return 0;
}

||

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
int global_val = 1;
static int static_global_val = 2;


struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int *static_val; // 使用指针进行访问,这是这是超出作用域最简单的方法
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int *_static_val, int flags=0) : static_val(_static_val) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int *static_val = __cself->static_val; // bound by copy

// 全局变量和静态全局变量可以直接使用
global_val ++;
static_global_val ++;

// 使用static_val的指针进行访问
(*static_val) ++;
}

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)};
int main(int argc, char const *argv[])
{
static int static_val = 3;

void (*blk)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &static_val));
return 0;
}

Block从栈赋值到堆上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#import <Foundation/Foundation.h>

typedef int (^blk_t)(int);

blk_t func(int rate) {
// return ^(int count) {return rate * count;}; // ARC下编译器会自动帮加上copy
return [^(int count) {return rate * count;} copy]; //MRC下需要手动copy
}

NSArray* getBlockArray {
return [NSArray alloc] initWithObjects:
[^{
NSLog(@"blk0");
}; copy],
[^{
NSLog(@"blk1");
}; copy],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
typedef int (*blk_t)(int);


struct __func_block_impl_0 {
struct __block_impl impl;
struct __func_block_desc_0* Desc;
int rate;
__func_block_impl_0(void *fp, struct __func_block_desc_0 *desc, int _rate, int flags=0) : rate(_rate) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static int __func_block_func_0(struct __func_block_impl_0 *__cself, int count) {
int rate = __cself->rate; // bound by copy
return rate * count;}

static struct __func_block_desc_0 {
size_t reserved;
size_t Block_size;
} __func_block_desc_0_DATA = { 0, sizeof(struct __func_block_impl_0)};
blk_t func(int rate) {
return ((int (*)(int))&__func_block_impl_0((void *)__func_block_func_0, &__func_block_desc_0_DATA, rate));
}