block本质

1、写一个简单的mac命令行程序,包含block定义与使用

1
2
3
4
5
6
7
8
9
10
11
#import <Foundation/Foundation.h>
 
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        void (^block)(void) = ^{
            NSLog(@"Hello block!");
        };
        block();
    }
    return 0;
}

2、在命令行下编译成c++源文件xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
3、得到的cpp文件有3万多行,找到尾部的main函数,与block相关的代码有:

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
// 1、block定义,结构体__main_block_impl_0
struct __block_impl {
    void *isa;
    int Flags;
    int Reserved;
    void *FuncPtr;
};
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;
    }
};
 
// 2.1、block体__main_block_func_0将做为参数传入block构造函数,__main_block_impl_0第一个参数
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
    // block内部代码
}
// 2.2、__main_block_impl_0构造函数第二个参数,__main_block_desc_0
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)};
 
/* 3、调用
 block = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA);
 block->FuncPtr(block);
 */
void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

4、总结:block本质是OC对象,block体等价于对象方法,在block体执行时会调用该方法;

2 thoughts on “block本质

  1. Sian Post author

    1、block中如果涉及到参数,在生成block对象中,block体执行函数会增加相对应的参数传递

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    #import <Foundation/Foundation.h>
     
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            void (^block)(int,int) = ^(int a, int b){
                NSLog(@"Hello block!, a = %d, b = %d", a, b);
            };
            block(10, 20);
        }
        return 0;
    }

    2、相关block对象中的执行函数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    // 1、block定义
    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;
      }
    };
    // 2、执行函数
    static void __main_block_func_0(struct __main_block_impl_0 *__cself, int a, int b) {
     
                NSLog((NSString *)&__NSConstantStringImpl__var_folders_hv___lpn_vs5cg5s51kph0qmkx40000gn_T_main_8b75f1_mi_0, a, b);
            }
  2. Sian Post author

    1、block中如果涉及到外部变量,在生成block对象时会新增相应的成员变量

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int a;
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };

    2、相对应的block结构体是这样的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            int a = 10;
            void (^block)(void) = ^(){
                NSLog(@"Hello block!, a = %d", a);
            };
            block();
        }
        return 0;
    }

Leave a Reply