IOS探索之Block的内部实现
2016-01-09 15:27
375 查看
这篇是记录根据网上的文章进行的实际操作。C函数的生成中间编译代码的编译方法是clang -rewrite-objc xxxx.c。由于编译文件中内容较多,这里我们只截取有关block的部分。
首先,看看没有block的C函数以及编译后的结果:
编译代码中的block:这里我们可以看到一个block的C实现。
*isa说明block也可以作为对象使用(例如我们定义一个myBlock类型的block1),指针变量FunPtr应该就是指向了block代码块的函数首地址
接着我们加一个block到.c文件中,并进行编译。
编译后:
3.假如我们要修改函数中局部变量的值,则需要加上__block修饰符,后面我们来看看为什么这样才可以修改。
编译后的cpp代码:
首先,看看没有block的C函数以及编译后的结果:
#include <stdio.h> int main(){ return 0; }
编译代码中的block:这里我们可以看到一个block的C实现。
#ifndef BLOCK_IMPL #define BLOCK_IMPL struct __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; }
相关文章推荐
- netty5笔记-总体流程分析4-NioServerSocketChannel
- netty5笔记-总体流程分析4-NioServerSocketChannel
- iOS:使用minimumScaleFactor控制字体大小自适应
- GitHub上最火的40个iOS开源项目
- GitHub上最火的40个iOS开源项目
- IOS开发系列——Masonry手写Autolayout专题【整理,部分原创】
- iOS中的沙盒及对沙盒内文件的常见操作
- 【iOS】CocoaPods初识、安装与使用
- 归档与反归档
- 快速部署安装nagios
- iOS 支付宝支付以及各种错误解决方法!!!
- IOS上怎样画出1像素的线
- ios 通知
- iOS学习之路-简单汤姆猫
- iOS中 KVC\KVO和通知三者之间的小结
- 【iOS】判断NSString字符串为空
- iOS: 枚举类型 enum,NS_ENUM,NS_OPTIONS
- iOS学习笔记:runtime(1)
- iOS 退出应用程序
- ios字符串截取/数据存入数组