首页 > 编程语言 >qemu源码分析(6)--Apple的学习笔记

qemu源码分析(6)--Apple的学习笔记

时间:2023-09-18 21:32:50浏览次数:55  
标签:__ obj Apple -- object dynamic 源码 type class

一,前言

由于看到了类似的写法,都用到了object_dynamic_cast_assert函数,所以分析下。

二,源码分析

  1. 看到如下代码的写法,很眼熟
CortexMBoardState *board = CORTEXM_BOARD_STATE(machine);

machine 的类型是MachineState *

#define CORTEXM_BOARD_STATE(obj) \
 OBJECT_CHECK(CortexMBoardState, (obj), TYPE_CORTEXM_BOARD)
 
#define OBJECT_CHECK(type, obj, name) \
 ((type *)object_dynamic_cast_assert(OBJECT(obj), (name), \
 __FILE__, __LINE__, __func__))
  1. 展开后就是
    ((CortexMBoardState *)object_dynamic_cast_assert(((Object *)((machine))), ("cortexm:" "machine"), __FILE__, __LINE__, __func__))
  2. 主要分析object_dynamic_cast_assert函数
Object *object_dynamic_cast_assert(Object *obj, const char *typename,
 const char *file, int line, const char *func)
{
……
inst = object_dynamic_cast(obj, typename);
……
}
Object *object_dynamic_cast(Object *obj, const char *typename)
{
 if (obj && object_class_dynamic_cast(object_get_class(obj), typename)) {
 return obj;
 }
 
 return NULL;
}
  1. 所以最主要的是object_class_dynamic_cast函数
ObjectClass *object_class_dynamic_cast(ObjectClass *class,
 const char *typename)
{
……
  /* 根据name直接找class */
 type = class->type;
 if (type->name == typename) {
 return class;
   }
/* 根据name来找到Type */
target_type = type_get_by_name(typename);
 if (type->class->interfaces &&
 type_is_ancestor(target_type, type_interface)) {
 ……
}
/* 根据父类的name来找type */ 
else if (type_is_ancestor(type, target_type)) {
 ret = class;
 }
}

上面我加的注释其实描述的不对,应为用了找class,其实class是传入的参数,是通过object_get_class(obj)传入的obj->class,而object是应用层machine将类型MachineState*强转为object*的。所以这里不能说找class,只能说check class。所以从宏定义的名字OBJECT_CHECK也看出这个函数的含义是检查用的。

object_dynamic_cast的返回类型是Object*,能赋值给CortexMBoardState*吗?直接赋值不可以,但是右边的值强转为object*是可以的,因为CortexMBoardState的首个元素就是Object类型的对象。

若我不检查,直接CortexMBoardState *board = (Object *)machine来赋值也可以,但是若参数machine中的object不存在为Null那么就会存在问题,所以用了这个OBJECT_CHECK来封装。

三,小结

这种就类似c++中的基类转为派生类,说不定c++源码的实现也是这样的设计,又学习到一招,这就是我喜欢底层的原因,因为能更加深入的了解设计方法及运行机制。



标签:__,obj,Apple,--,object,dynamic,源码,type,class
From: https://blog.51cto.com/u_16247275/7516182

相关文章

  • 【Azure Batch】在中国区批处理服务(Mooncake Batch Account)上实验自动池(Auto Pool)
    问题描述在AzureBatch的介绍文档中,提出了自动池的概念,它可以在任务完成后,自动删除Pool资源,详细介绍:https://docs.azure.cn/zh-cn/batch/nodes-and-pools#autopools & https://learn.microsoft.com/zh-cn/rest/api/batchservice/job/add?tabs=HTTP#autopoolspecification自动池......
  • Cisco STP
    IEEE802.1d是IEEE(InstituteofElectricalandElectronicsEngineers)开发的标准文档之一,它确定了生成树协议(SpanningTreeProtocol)的操作规程和标准,目的是解决交互式局域网内的冗余链路造成的环路问题,同时提供故障冗余恢复功能。......
  • Docker常用命令
    1、docker安装docker:yuminstall-ydocker-ce关闭防火墙:systemctlstopfirewalld启动:systemctlstartdocker设置开机启动:systemctlenabledocker重启操作系统后生效停止:systemctlstopdocker重启:systemctlrestartdocker2、镜像查看本地镜像:d......
  • 五、文件搜索命令
    5.1 查找文件:find命令    Linuxfind命令用来在指定目录下查找文件。任何位于参数之前的字符串都将被视为欲查找的目录名。如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示。find命令有非常大的......
  • nginx-缓存
    缓存内容并定义缓存的存储位置。proxy_cache_path/var/nginx/cache               keys_zone=CACHE:60m               levels=1:2                        ......
  • 第一题 两数之和(Map功能描述待完成)
    先是我的暴力解法(有点菜):1classSolution{2publicint[]twoSum(int[]nums,inttarget){3for(inti=0;i<nums.length-1;i++)4{5for(intj=i+1;j<nums.length;j++)6{7if(nu......
  • 软工日报23-9-18
    学习时长:3h解决问题:今天学习了一些vue的知识,下面是学习的一些依赖的展示代码量:200行"dependencies":{"axios":"^1.5.0","core-js":"^3.8.3","element-ui":"^2.15.14","vue":"^2.6.14&q......
  • 《看了受制了》第二十天,6道题,合计90道题
    2023年9月18日今天上午写了Atcoder的翻译,以后对于我这种菜鸡来说,多多少少有点用了。前两个题是贪心,第三个是BFS。Acwing908最大不相交区间数量题目理解全部按右端点进行排序然后如果下一个点的左,比我的右端点还大,那么就肯定不在一个区间然后更新目前的右端点即可代码实......
  • 使用ztncui配置私有化zerotier服务器
    众所周知,Zerotier-One是一个非常好的组建虚拟局域网的工具,可以以p2p的方式穿透NAT网络进行连接。但是在使用中也仍然存在着一些瑕疵,主要就是以下两点:因为Zerotier官方提供的中心节点(planet节点)全部都在国外,所以更新路由表的时候,通常会消耗较长的时间,甚至可能失败;官方免费版......
  • vue-dayu03
    js循环方式一:基于索引的循环<script>leti=0for(;i<10;){console.log(i)i++}letgood_list=[1,2,3]for(letj=0;j<good_list.length;j++){console.log(good_list[j])}</script>方式二:in循环  基于迭代的循环,依赖于索引取......