介绍怎么样在GObject类型系统中注册一个类型。
注册类型
g_type_register_static用来向类型系统注册新的类型。所有的类型都需要定义以下信息,它们都以函数指针的方式包含在一个GTypeInfo对象中,并且作为g_type_register_static的参数提供给类型系统:
- class size: class_size .
- class initialization functions (C++ constructor): base_init and class_init .
- class destruction functions (C++ destructor): base_finalize and class_finalize .
- instance size (C++ parameter to new): instance_size .
- instantiation policy (C++ type of new operator): n_preallocs.
- copy functions (C++ copy operators): value_table .
- type characteristic flags: GTypeFlags .
每个类型都必须定义两个结构:类结构与实例结构。类结构的第一个成员必须是GTypeClass类型,而实例结构的第一个成员必须是GTypeInstance 类型。类结构存放的是一个类型的公共信息,类似C++中的成员函数和静态成员变量;而实例结构存放的是一个类型的各个实例所特有的信息,在类型系统中具有多个每个实例的实例结构都可以不同,类似C++中的普通成员变量。
下面的例子告诉我们怎样在类型系统中注册一个类并用g_object_new获得这个类的一个实例:
类型与实例的初始化
上面提到了注册系统时需要的三个初始化函数,instance_init提供了实例结构(例如MamanBar)的初始化,而base_init和class_init提供了类结构(例如MamanBarClass)的初始化。那么base_init和class_init有什么区别呢?当存在继承关系时,直接拷贝不能完整地拷贝信息时,就需要base_init。例如下面的代码将字符串的初始化放在base_init中。
typedef struct { GObjectClass parent_class; gint static_integer; gchar *dynamic_string; } TypeAClass; static void type_a_base_init (TypeAClass *class) { class->dynamic_string = g_strdup ("some string"); } static void type_a_base_finalize (TypeAClass *class) { g_free (class->dynamic_string); } static void type_a_class_init (TypeAClass *class) { class->static_integer = 42; } typedef struct { TypeAClass parent_class; gfloat static_float; GString *dynamic_gstring; } TypeBClass; static void type_b_base_init (TypeBClass *class) { class->dynamic_gstring = g_string_new ("some other string"); } static void type_b_base_finalize (TypeBClass *class) { g_string_free (class->dynamic_gstring); } static void type_b_class_init (TypeBClass *class) { class->static_float = 3.1415926; }
继承关系
如果要让类型B继承类型A,只要使A的类结构和实例结构分别作为B的类结构和实例结构的第一个成员。