Block的实现原理

来源:互联网 发布:mac下制作winpe 编辑:程序博客网 时间:2024/05/20 05:23

Block的实现原理

这篇是记录根据网上的文章进行的实际操作。C函数的生成中间编译代码的编译方法是clang -rewrite-objc xxxx.c。由于编译文件中内容较多,这里我们只截取有关block的部分。

首先,看看没有block的C函数以及编译后的结果:

#include <stdio.h>int main(){    return 0;}

编译代码中的block:这里我们可以看到一个block的C实现。

#ifndef BLOCK_IMPL#define BLOCK_IMPLstruct __block_impl {  void *isa;  int Flags;  int Reserved;  void *FuncPtr;};

*isa说明block也可以作为对象使用(例如我们定义一个myBlock类型的block1),指针变量FunPtr应该就是指向了block代码块的函数首地址

接着我们加一个block到.c文件中,并进行编译。

#include <stdio.h>int main(){int i = 10;void(^myBlock)(void) = ^(void){    printf("hello world! %d\n",i);};myBlock();return 0;}

编译后:

struct __main_block_impl_0 {  struct __block_impl impl;  struct __main_block_desc_0* Desc;  int i;  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _i, int flags=0) : i(_i) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};static void __main_block_func_0(struct __main_block_impl_0 *__cself) {  int i = __cself->i; // bound by copy  printf("hello world! %d\n",i); }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 i = 10; void(*myBlock)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, i); ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock); return 0;}

3.假如我们要修改函数中局部变量的值,则需要加上__block修饰符,后面我们来看看为什么这样才可以修改。

#include <stdio.h>int main(){__block int i = 10;void(^myBlock)(void) = ^(void){i = 12;    printf("hello world! %d\n",i);};myBlock();return 0;}

编译后的cpp代码:

struct __Block_byref_i_0 {  void *__isa;__Block_byref_i_0 *__forwarding; int __flags; int __size; int i;};struct __main_block_impl_0 {  struct __block_impl impl;  struct __main_block_desc_0* Desc;  __Block_byref_i_0 *i; // by ref  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) {    impl.isa = &_NSConcreteStackBlock;    impl.Flags = flags;    impl.FuncPtr = fp;    Desc = desc;  }};static void __main_block_func_0(struct __main_block_impl_0 *__cself) {  __Block_byref_i_0 *i = __cself->i; // bound by ref  (i->__forwarding->i) = 12;  printf("hello world! %d\n",(i->__forwarding->i)); }static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->i, (void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);}static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);}static struct __main_block_desc_0 {  size_t reserved;  size_t Block_size;  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);  void (*dispose)(struct __main_block_impl_0*);} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};int main(){ __attribute__((__blocks__(byref))) __Block_byref_i_0 i = {(void*)0,(__Block_byref_i_0 *)&i, 0, sizeof(__Block_byref_i_0), 10}; void(*myBlock)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_i_0 *)&i, 570425344); ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock); return 0;}
1 0
原创粉丝点击