类型、对象和接口之间的转换
因为用c语言实现了一个类面向对象的设备模型,在类型和实例之间的转换都需要手工实现。所以在代码中有几个重要的宏定义来完成这样的工作。
obj -> class
对应的obj找到它的class。
obj就是我们传入的对象实例, object_get_class就是获得obj->class这个成员,也就是对应的class。 class就是这个对象对应的class的类型,name呢就是这个class的名字。 对于没有intefaces的类型来说,这就是一个强制类型转换。也就是得到了obj对应的类型。
ObjectClass -> 子Class
在上面的图中我们也看到,类型之间也有着父子关系。比如PCIDeviceClass就是DeviceClass的子类。
所以有时候在代码中我们需要从父类获得具体的子类。这个工作交给了:
这个宏其实就是上面的那个宏,如果没有interfaces成员这也是一个强制类型转换。把class类型转换成class_type。
但是因为Qemu自身的面向对象的模型,子类和父类的基地址相同所以能够通过强制转换来得到子类。
其实这么看,反过来转换也是可以的。
Object -> 子Object
同上面的类型一样,object也有父子关系。所以当代码中需要从父对象转换到一个具体的子对象时就要用:
对obj来讲就没有类型Class这么复杂了,在生产环境中纯粹就是强制类型转换,把obj类型转换到type类型。 因为按照Qemu的面向对象模型,父子obj的基地址是一样的。
Class -> InterfaceClass
这个转换和Class到子Class的方式一样,也是
但是因为这个Class有interfaces成员,所以会在interfaces链表上查找名字为name的接口。
如果有则返回对应name的接口。
Object -> Interface
从上面的转换可以看出,如果想要从一个obj得到interface可以分成两步:
obj -> class
class -> interface
但是因为当Class有interface成员,且传入的name就是接口类型的名字时,obj可以直接转换成接口。
也就是用OBJECT_CLASS_CHECK可以直接转换得到。
obj -> 虚obj
所以虚obj就是obj对象对应的Class类型的接口类型的对象。这么说还真有点绕,估计我自己过段时间来看也得花点时间回忆回忆。
之所以我叫它虚obj,是因为接口类型本身是没有对应的对象的。所以这个东西还挺神奇,没想到代码里还会这么用。
大家也一定觉得不信,那先举个例子:
这个MemoryDeviceState就定义了这么一个类型,没有任何的成员。而它对应的Class类型是TYPE_MEMORY_DEVICE的接口类型。
而在代码中通常的用法还是要将这个虚obj再转换到接口类型。通常用法如下:
这个obj就是一个真实的obj对象,而md则是对应的虚obj。其实他们俩的指是一样的,都指向了同一个地址。
还是觉得很神奇,为什么代码要这么写呢?就不能直接传obj么?
我能想到的一个作用就是在debug选项打开时能够检测类型,而不至于传错参数。
Last updated