GLib类型系统

介绍怎么样在GObject类型系统中注册一个类型。

注册类型

typedef struct _GTypeInfo GTypeInfo; struct _GTypeInfo { /* interface types, classed types, instantiated types */ guint16 class_size; GBaseInitFunc base_init; GBaseFinalizeFunc base_finalize; /* classed types, instantiated types */ GClassInitFunc class_init; GClassFinalizeFunc class_finalize; gconstpointer class_data; /* instantiated types */ guint16 instance_size; guint16 n_preallocs; GInstanceInitFunc instance_init; /* value handling */ const GTypeValueTable *value_table; }; GType g_type_register_static (GType parent_type, const gchar *type_name, const GTypeInfo *info, GTypeFlags flags); 

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获得这个类的一个实例:

typedef struct { GObject parent; /* instance members */ int field; } MamanBar; typedef struct { GObjectClass parent; /* class members */ void (*do_action) (MamanBar *self, guint8 i); } MamanBarClass; GType maman_bar_get_type (void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(MamanBarClass), NULL, /* base_init */ NULL, /* base_finalize */ NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ sizeof(MamanBar), 0, /* n_preallocs */ NULL /* instance_init */ }; type = g_type_register_static (G_TYPE_OBJECT, "BarType", &info, 0); } return type; } MamanBar* bar = reinterpret_castg_object_new(maman_bar_get_type(), 0);


类型与实例的初始化

上面提到了注册系统时需要的三个初始化函数,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的类结构和实例结构的第一个成员。

/* A definitions */ typedef struct { GTypeInstance parent; int field_a; } A; typedef struct { GTypeClass parent_class; void (*method_a) (void); } AClass; /* B definitions. */ typedef struct { A parent; int field_b; } B; typedef struct { AClass parent_class; void (*method_b) (void); } BClass; 

 

 

你可能感兴趣的:(C/C++)