接前一篇文章: QEMU源码全解析27 —— QOM介绍(16)
本文内容参考:
《 QEMU /KVM》源码解析与应用 —— 李强,机械工业出版社
特此致谢!
在 QEMU源码全解析25 —— QOM介绍(14) 中讲到属性的添加分为类属性的添加和对象属性的添加。而后就一直沿着对象属性的添加这一支走下来了,现在我们翻回头来讲解另外一支 —— 类属性的添加。
对于对象属性来说,其属性添加是通过qom/object.c中的object_property_add接口完成的。那么与之对应,类的属性的添加函数为object_class_property_add,也在qom/object.c中(实际就在object_property_add函数的下边),代码如下:
- ObjectProperty *
- object_class_property_add(ObjectClass *klass,
- const char *name,
- const char *type,
- ObjectPropertyAccessor *get,
- ObjectPropertyAccessor *set,
- ObjectPropertyRelease *release,
- void *opaque)
- {
- ObjectProperty *prop;
-
- assert(!object_class_property_find(klass, name));
-
- prop = g_malloc0(sizeof(*prop));
-
- prop->name = g_strdup(name);
- prop->type = g_strdup(type);
-
- prop->get = get;
- prop->set = set;
- prop->release = release;
- prop->opaque = opaque;
-
- g_hash_table_insert(klass->properties, prop->name, prop);
-
- return prop;
- }
这个函数倒没有像object_property_add函数那样又调用了一层object_property_try_add函数,而是直接在本函数中就实现了与object_property_try_add函数中类似的功能(代码很类似)。对比一下object_property_try_add函数代码:
- ObjectProperty *
- object_property_try_add(Object *obj, const char *name, const char *type,
- ObjectPropertyAccessor *get,
- ObjectPropertyAccessor *set,
- ObjectPropertyRelease *release,
- void *opaque, Error **errp)
- {
- ObjectProperty *prop;
- size_t name_len = strlen(name);
-
- ……
-
- if (object_property_find(obj, name) != NULL) {
- error_setg(errp, "attempt to add duplicate property '%s' to object (type '%s')",
- name, object_get_typename(obj));
- return NULL;
- }
-
- prop = g_malloc0(sizeof(*prop));
-
- prop->name = g_strdup(name);
- prop->type = g_strdup(type);
-
- prop->get = get;
- prop->set = set;
- prop->release = release;
- prop->opaque = opaque;
-
- g_hash_table_insert(obj->properties, prop->name, prop);
- return prop;
- }
可以看到,相似度很高,说明对象和类的属性的处理流程是差不多的,无非就是将Object *obj换成了ObjectClass *klass。
首先调用object_class_property_find函数来确认所插入的类属性是否已经存在。如果已存在,则报错返回,确保不会添加重复的属性。
随后分配一个ObjectProperty结构并使用函数参数进行初始化。代码片段如下(这一步与object_property_try_add中完全一样):
- prop = g_malloc0(sizeof(*prop));
-
- prop->name = g_strdup(name);
- prop->type = g_strdup(type);
-
- prop->get = get;
- prop->set = set;
- prop->release = release;
- prop->opaque = opaque;
最后,调用以下代码将其插入到对象的properties域中,并返回此prop:
g_hash_table_insert(obj->properties, prop->name, prop);
回过头来,看一下object_class_property_find函数的具体实现。object_class_property_find函数在同文件(qom/object.c)中,代码如下:
- ObjectProperty *object_class_property_find(ObjectClass *klass, const char *name)
- {
- ObjectClass *parent_klass;
-
- parent_klass = object_class_get_parent(klass);
- if (parent_klass) {
- ObjectProperty *prop =
- object_class_property_find(parent_klass, name);
- if (prop) {
- return prop;
- }
- }
-
- return g_hash_table_lookup(klass->properties, name);
- }
其实类的属性的添加反倒比对象的属性的添加简单,因为对象的属性添加中还是调用的这里的object_class_property_find函数。这个函数的作用之前也讲过,确保自己所属的类以及所有父类都不存在这个属性。
下一回讲解类的属性的设置和获取。