接前一篇文章: QEMU源码全解析15 —— QOM介绍(4)
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
上一回讲完了QOM第一部分 —— 类型的注册。本回开始讲解第二部分 —— 类型的初始化。
2. 类型的初始化
在C++、Java等 面向对象编程 语言中,当程序中声明一个类型的时候,就已经知道了其类型的信息,如它的对象的大小。但是如果使用C语言来实现面向对象的这些特性,就需要特殊的处理了,要对类进行单独的初始化。在前文中,所有的类型信息TypeImpl已经保存在了一个哈希链表中,接下来,就需要对类进行初始化了。
类的初始化是通过type_initialize函数完成的,其在qom/object.c中,代码如下:
- static void type_initialize(TypeImpl *ti)
- {
- TypeImpl *parent;
-
- if (ti->class) {
- return;
- }
-
- ti->class_size = type_class_get_size(ti);
- ti->instance_size = type_object_get_size(ti);
- /* Any type with zero instance_size is implicitly abstract.
- * This means interface types are all abstract.
- */
- if (ti->instance_size == 0) {
- ti->abstract = true;
- }
- if (type_is_ancestor(ti, type_interface)) {
- assert(ti->instance_size == 0);
- assert(ti->abstract);
- assert(!ti->instance_init);
- assert(!ti->instance_post_init);
- assert(!ti->instance_finalize);
- assert(!ti->num_interfaces);
- }
- ti->class = g_malloc0(ti->class_size);
-
- parent = type_get_parent(ti);
- if (parent) {
- type_initialize(parent);
- GSList *e;
- int i;
-
- g_assert(parent->class_size <= ti->class_size);
- g_assert(parent->instance_size <= ti->instance_size);
- memcpy(ti->class, parent->class, parent->class_size);
- ti->class->interfaces = NULL;
-
- for (e = parent->class->interfaces; e; e = e->next) {
- InterfaceClass *iface = e->data;
- ObjectClass *klass = OBJECT_CLASS(iface);
-
- type_initialize_interface(ti, iface->interface_type, klass->type);
- }
-
- for (i = 0; i < ti->num_interfaces; i++) {
- TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
- if (!t) {
- error_report("missing interface '%s' for object '%s'",
- ti->interfaces[i].typename, parent->name);
- abort();
- }
- for (e = ti->class->interfaces; e; e = e->next) {
- TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
-
- if (type_is_ancestor(target_type, t)) {
- break;
- }
- }
-
- if (e) {
- continue;
- }
-
- type_initialize_interface(ti, t, t);
- }
- }
-
- ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
- object_property_free);
-
- ti->class->type = ti;
-
- while (parent) {
- if (parent->class_base_init) {
- parent->class_base_init(ti->class, ti->class_data);
- }
- parent = type_get_parent(parent);
- }
-
- if (ti->class_init) {
- ti->class_init(ti->class, ti->class_data);
- }
- }
type_initialize函数比较长,分段进行解析。
函数的参数(入参)是表示类型信息的TypeImpl类型的对象ti的地址或指针。type_initialize函数首先判断ti->class是否存在,如果不为空,则说明这个类型已经初始化过了,直接返回。
后边主要做了三件事:
(1)设置相关的field,如class_size和instance_size,并使用ti->class_size分配一个ObjectClass。代码片段如下:
- ti->class_size = type_class_get_size(ti);
- ti->instance_size = type_object_get_size(ti);
- /* Any type with zero instance_size is implicitly abstract.
- * This means interface types are all abstract.
- */
- if (ti->instance_size == 0) {
- ti->abstract = true;
- }
- if (type_is_ancestor(ti, type_interface)) {
- assert(ti->instance_size == 0);
- assert(ti->abstract);
- assert(!ti->instance_init);
- assert(!ti->instance_post_init);
- assert(!ti->instance_finalize);
- assert(!ti->num_interfaces);
- }
- ti->class = g_malloc0(ti->class_size);
为便于理解,再贴一下TypeImpl结构的定义(在qom/object.c中):
- truct TypeImpl
- {
- const char *name;
-
- size_t class_size;
-
- size_t instance_size;
- size_t instance_align;
-
- void (*class_init)(ObjectClass *klass, void *data);
- void (*class_base_init)(ObjectClass *klass, void *data);
-
- void *class_data;
-
- void (*instance_init)(Object *obj);
- void (*instance_post_init)(Object *obj);
- void (*instance_finalize)(Object *obj);
-
- bool abstract;
-
- const char *parent;
- TypeImpl *parent_type;
-
- ObjectClass *class;
-
- int num_interfaces;
- InterfaceImpl interfaces[MAX_INTERFACES];
- };
(2)(递归)初始化所有父类型,不仅包括实际的类型,还包括接口这种抽象类型。代码片段如下:
- parent = type_get_parent(ti);
- if (parent) {
- type_initialize(parent);
- GSList *e;
- int i;
-
- g_assert(parent->class_size <= ti->class_size);
- g_assert(parent->instance_size <= ti->instance_size);
- memcpy(ti->class, parent->class, parent->class_size);
- ti->class->interfaces = NULL;
-
- for (e = parent->class->interfaces; e; e = e->next) {
- InterfaceClass *iface = e->data;
- ObjectClass *klass = OBJECT_CLASS(iface);
-
- type_initialize_interface(ti, iface->interface_type, klass->type);
- }
-
- for (i = 0; i < ti->num_interfaces; i++) {
- TypeImpl *t = type_get_by_name(ti->interfaces[i].typename);
- if (!t) {
- error_report("missing interface '%s' for object '%s'",
- ti->interfaces[i].typename, parent->name);
- abort();
- }
- for (e = ti->class->interfaces; e; e = e->next) {
- TypeImpl *target_type = OBJECT_CLASS(e->data)->type;
-
- if (type_is_ancestor(target_type, t)) {
- break;
- }
- }
-
- if (e) {
- continue;
- }
-
- type_initialize_interface(ti, t, t);
- }
- }
-
- ti->class->properties = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
- object_property_free);
-
- ti->class->type = ti;
(3)依次调用所有父类的class_base_init以及自己的class_init函数。这也和C++类似,在初始化一个对象的时候会依次调用所有父类的构造函数。
- while (parent) {
- if (parent->class_base_init) {
- parent->class_base_init(ti->class, ti->class_data);
- }
- parent = type_get_parent(parent);
- }
-
- if (ti->class_init) {
- ti->class_init(ti->class, ti->class_data);
- }
实际上,type_initialize函数可以在很多地方调用,不过,只有在第一次调用的时候会进行初始化,之后的调用会由于ti->class不为空,在函数开始处就直接返回了。
欲知后事如何,且看下回分解。