傻瓜学编程之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: ...
随机推荐
- 3.9 run_main.py源码(兼容python2和3)
3.9 run_main.py源码(兼容python2和3) 以下代码在python2和python3上都跑通过,python3只需注释掉上面红色框框区域代码就行(最后一步发送邮箱代码,我注释掉了). ...
- spark学习笔记_1
简单的讲,Apache Spark是一个快速且通用的集群计算系统. Apache Spark 历史: 2009年由加州伯克利大学的AMP实验室开发,并在2010年开源,13年时成长为Apache旗下大 ...
- Python学习之路基础篇--09Python基础,初识函数
函数可以分为内置函数 和 自定义函数.这次关注的主要是自定义函数.定义函数之后,就可以在任何需要它的地方调用. 1 返回值的重要性 返回值的3种情况 没有返回值 ---- 返回None 不定 retu ...
- Python全栈之路----常用模块----hashlib加密模块
加密算法介绍 HASH Python全栈之路----hash函数 Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列 ...
- SSH与MVC
MVC是一个框架模式,它强制性的使应用程序的输入.处理和输出分开.使用MVC应用程序被分成三个核心部件:模型.视图.控制器.它们各自处理自己的任务.最典型的MVC就是JSP + servlet + j ...
- SERvet的表单
首先要建立好数据库. 好了,先写好两个静态页面,分别负责登录和注册. 代码清单1:login.jsp(登录页面) <%-- Document : login Created on : 2013- ...
- Qt学习2---信号与槽
connect(&b1,&QPushButton::pressed,this,&MainWidget::close); &b1:信号发出者,指针类型 &QPus ...
- myEclipse出现cannot paste the clipboard contents into the selected elements报错
导入jar包报错,cannot paste the clipboard contents into the selected elements,查阅资料让重新打开工程,但依然报错. 最后在本地路径复制 ...
- UT源码 105032014098
package exam1; import java.util.Scanner; public class test01 { static String nextDate(int year,int m ...
- vue2上传图片到OSS
第一步:安装阿里云OSS <!-- 引入在线资源 --> <script src="http://gosspublic.alicdn.com/aliyun-oss-sdk- ...