傻瓜学编程之block_2
block的实质
以一个简单的实现为列子;
- (void)myBlcokTest{
void (^blk)()=^{
printf(@“beijinghuanyingni”);
};
blk();
}
终端:clang -rewrite-objc 类文件名.m
cpp文件中关键代码:
static void _I_People_myBlcokTest(People * self, SEL _cmd) {
void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
}
static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
}
struct __People__myBlcokTest_block_impl_0 {
struct __block_impl impl;
struct __People__myBlcokTest_block_desc_0* Desc;
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_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 __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
} __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};
运行时的myBlcokTest方法;
static void _I_People_myBlcokTest(People * self, SEL _cmd) {
void (*blk)()=((void (*)())&__People__myBlcokTest_block_impl_0((void *)__People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
}
去掉类型转化
static void _I_People_myBlcokTest(People * self, SEL _cmd) {
__People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0, &__People__myBlcokTest_block_desc_0_DATA));
、、、
}
__People__myBlcokTest_block_impl_0:是一个结构体 包含两个成员:
struct __block_impl impl;
struct __People__myBlcokTest_block_desc_0* Desc; 以及一个构造函数:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
struct __People__myBlcokTest_block_impl_0 {
成员一: struct __block_impl impl; // __block_impl结构体
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
成员二: struct __People__myBlcokTest_block_desc_0* Desc;//__People__myBlcokTest_block_desc_0结构体
static struct __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
}
构造函数:
构造函数中成员的处理 在后面 构造函数中参数的处理部分解释;
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
通过结构体的构造函数生成一个block实例
__People__myBlcokTest_block_impl_0 blk = __People__myBlcokTest_block_impl_0( __People__myBlcokTest_block_func_0,
&__People__myBlcokTest_block_desc_0_DATA)); 构造函数参数的意义:
参数一: __People__myBlcokTest_block_func_0 //函数实现地址 在把函数赋值给函数指针的时候可以省略&;
在构造函数参数的意义: 把函数的地址赋值给指针 void *fp
函数的具体实现代码:
static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
}
这里面的__cself是什么后面会解释;
参数二: &__People__myBlcokTest_block_desc_0_DATA // __People__myBlcokTest_block_desc_0的默认初始化
{ 0, sizeof(struct __People__myBlcokTest_block_impl_0) //使用__People__myBlcokTest_block_impl_0的大小进行初始化
具体代码:
static struct __People__myBlcokTest_block_desc_0 {
size_t reserved;// 升级版本所需要的区域
size_t Block_size;//block大小
} __People__myBlcokTest_block_desc_0_DATA = { 0, sizeof(struct __People__myBlcokTest_block_impl_0)};
函数指针 与指针函数点击这里
构造函数中参数的处理
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
赋值之后:
__People__myBlcokTest_block_impl_0(void *fp, struct __People__myBlcokTest_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;//_NSConcreteStackBlock用于初始化isa成员 后面具体解释
impl.Flags = 0;
impl.FuncPtr =__People__myBlcokTest_block_func_0;
imlp.Reserved=0;
Desc =__People__myBlcokTest_block_desc_0_DATA;
}
再来看看block的调用:
blk();
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
简化
((__block_impl *)blk)->FuncPtr)((__block_impl *)blk); =>(blk ->FuncPtr)(blk)
获取blk结构体中函数指针FuncPtr 通过该函数指针调用函数 并且参数值为blk 点击这里;
这个等价于
(blk ->FuncPtr)(blk) 相当于
blk -> __People__myBlcokTest_block_func_0(blk);
再看看
static void __People__myBlcokTest_block_func_0(struct __People__myBlcokTest_block_impl_0 *__cself) {
printf("woshinidexiaodaye");
}
说明 __cself 就是blk 本身;
傻瓜学编程之block_2的更多相关文章
- 傻瓜学编程之block_3
block 捕获自动变量的瞬间值: 注释在代码中:请参考傻瓜学编程之block_3 import "People.h" @interface People() { int your ...
- 傻瓜学编程之block_1
1.引出 1.1.int pp = 3;for循环为dd赋值并 调用 finprint(int ,int)函数 获取pp*dd的乘积,输出 void finalValue(int d, int sca ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- 2017“编程之美”终章:AI之战勇者为王
编者按:8月15日,第六届微软“编程之美”挑战赛在选手的火热比拼中圆满落下帷幕.“编程之美”挑战赛是由微软主办,面向高校学生开展的大型编程比赛.自2012年起,微软每年都在革新比赛命题.紧跟时代潮流, ...
- 网络编程之TCP/IP各层详解
网络编程之TCP/IP各层详解 我们将应用层,表示层,会话层并作应用层,从TCP/IP五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议,就理解了整个物联网通信的原理. 首先,用户感知到的只 ...
- Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)
Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享) 点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...
- Python网络编程之TCP套接字简单用法示例
Python网络编程之TCP套接字简单用法示例 本文实例讲述了Python网络编程之TCP套接字简单用法.分享给大家供大家参考,具体如下: 上学期学的计算机网络,因为之前还未学习python,而jav ...
- Python Flask高级编程之从0到1开发《鱼书》精品项目
Python Flask高级编程之从0到1开发<鱼书>精品项目 整个课程都看完了,这个课程的分享可以往下看,下面有链接,之前做java开发也做了一些年头,也分享下自己看这个视频的感 ...
- Java并发编程之CAS二源码追根溯源
Java并发编程之CAS二源码追根溯源 在上一篇文章中,我们知道了什么是CAS以及CAS的执行流程,在本篇文章中,我们将跟着源码一步一步的查看CAS最底层实现原理. 本篇是<凯哥(凯哥Java: ...
随机推荐
- HBase学习笔记1 - 如何编写高性能的客户端Java代码
转载请标注原链接:http://www.cnblogs.com/xczyd/p/5577124.html 客户在使用HBase的时候,经常会抱怨说写入太慢,并发上不去等等.从前我遇到这种情况,一般都二 ...
- JavaScript语言里判断一个整数是偶数还是奇数,并输出判断结果
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- python笔记-数学、元组、日期、文件
python在很多地方和C++相似,比如都会有关系.逻辑等运算符,但也有不同的地方,比如:#Python Number 类型转换int(x [,base ]) 将x转换为一个整数 long(x [,b ...
- 【Effective Java读书笔记】创建和销毁对象(一):考虑使用静态工厂方法代替构造器
类可以提供一个静态方法,返回类的一个静态实例,如Boolean包装类的一个获取实例的静态方法 public static Boolean valueOf(boolean b) { return (b ...
- 同步I/O、异步I/O与阻塞I/O、非阻塞I/O的区别
一.I/O I/O (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作. 通常用户进程中的一个完整I/O分为两阶段:用户进程空间<-->内核空间.内核空间< ...
- linux文本处理命令
linux文本处理命令 1.wc命令 基本介绍 文件的行统计.字符统计.字节统计 基本语法 wc [OPTION]... [FILE]... wc [OPTION]... --files0-f ...
- Byte数组和字符串相互转换的问题
第一:需求:将文件转成byte数组,之后转成字符串返回.过滤器接收到响应内容后,需要将响应的内容转成byte数组. 第二:我刚开始的做法: Controller:byteArr = Conversio ...
- vlookup使用
数据处理过程中,需要excel进行简单的操作,比如vlookup,摸索之后,总结如下:
- listview 点击时间被拦截
记录下自己所犯的错误,在写ListView的点击事件时OnItemClickListener,onItemClick方法没有执行,导致ListView条目点击事件失效,检查发现百度上有很多不同的答案, ...
- java-递归练习
1.从键盘接收一个文件夹路径,统计该文件夹大小 public class Test1 { /** * @param args * 需求:1,从键盘接收一个文件夹路径,统计该文件夹大小 * * 从键盘接 ...