GObject参考手册(3)--GLib动态类型系统

 本文引用自http://imtx.cn,原文作者:TualatriX 

 

原文:http://library.gnome.org/devel/gobject/2.14/chapter-gtype.html

由Glib类型系统操作的一个类型,比传统上所讲的Object类型更具一般化。下面查看类型系统中有关类结构和注册新类型的函数,是会对此最好的解释。

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);
GType g_type_register_fundamental (GType                       type_id,
                                   const gchar                *type_name,
                                   const GTypeInfo            *info,
                                   const GTypeFundamentalInfo *finfo,
                                   GTypeFlags                  flags);

g_type_register_static和g_type_register_fundamental这两个C函数定义在gtype.h中,并在gtype.c中具体实现。你可以用来在程序的类型系统中注册一个新的GType。一般情况下你永远也不需要使用g_type_register_fundamental(除非你是Tim Janik才会这样做),但是这次你要做,在最后一章会向你解释如何创建一个基本类型。

基本类型是不需要从任何其他类型取得的最顶级的类型, 相对的,其他非基本类型是继承于其他类型的。在由g_type_init初始化时,类型系统不仅仅初始化它的内部数据结构,同时也注册一些核心类型:其中一些是基本类型,其他则是从基本类型继承的。

不论是基本还是非基本类型,均由下面的定义步骤:

  • 类的大小:GTypeInfo的class_size。
  • 类的初始化函数(C++ 构造函数):GTypeInfo的base_init和class_init。
  • 类的销毁函数(C++析构函数):GTypeInfo的base_finalize和class_finalize。
  • 实例的大小(C++参数new):GTypeInfo中的instance_size。
  • 实例化策略(C++ 类的new operator):GTypeInfo的n_preallocs。
  • 复制函数(C++的复制操作):GTypeInfo的value_table。
  • 类的字符标志:GTypeFlags。

基本类型同样可以由GTypeFundamentalFlags来定义,并保存在GTypeFundamentallInfo中。非基本类型一般传递一个parent_type至g_type_register_static和g_type_register_dynamic中,然后交给父类来定义。

复制函数

所有的glib类型(基本和非基本,类化和非类化,可实例化和不可实例化)的最大共同点是都可以通过单一的API来复制或指定它们。

GValue结构被用作所有类型的抽象的容器,它的极度简化的API(定义在gobject/gvalue.h)可以被使用请求value_table函数被注册当类型注册中:举个例子,g_value_copy复制了GValue的内容至另一个GValue。这与C++指派它的复制操作来修改默认的按位复制C++/C结构是类似的。

下面的代码向你展示了你是如何复制一个64位的整型,同样GObject的实例指针也是这样(代码在/gtype/test.c中):

static void test_int (void)
{
  GValue a_value = {0, };
  GValue b_value = {0, };
  guint64 a, b;

  a = 0xdeadbeaf;

  g_value_init (&a_value, G_TYPE_UINT64);
  g_value_set_uint64 (&a_value, a);

  g_value_init (&b_value, G_TYPE_UINT64);
  g_value_copy (&a_value, &b_value);

  b = g_value_get_uint64 (&b_value);

  if (a == b) {
    g_print ("Yay !! 10 lines of code to copy around a uint64./n");
  } else {
    g_print ("Are you sure this is not a Z80 ?/n");
  }
}

static void test_object (void)
{
  GObject *obj;
  GValue obj_vala = {0, };
  GValue obj_valb = {0, };
  obj = g_object_new (MAMAN_BAR_TYPE, NULL);

  g_value_init (&obj_vala, MAMAN_BAR_TYPE);
  g_value_set_object (&obj_vala, obj);

  g_value_init (&obj_valb, G_TYPE_OBJECT);

  /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
     This function thus calls g_object_ref.
     It is interesting to note that the assignment works here because
     MAMAN_BAR_TYPE is a G_TYPE_OBJECT.
   */
  g_value_copy (&obj_vala, &obj_valb);

  g_object_unref (G_OBJECT (obj));
  g_object_unref (G_OBJECT (obj));
}

上面代码的重点是关于复制指令的确切语义,并没有详细的定义复制是如何实现的。复制函数的实现可能是决定请求一新块的内存,并把数据从源复制到目的。或者可能是简单的增加实例的引用数和复制引用至新的GValue。

value_table用于详细说明这些定义在gtype.h的函数的使用并彻底地描述在由GObject提供的API文档中,这是为什么我们不追究细节的原因。

typedef struct _GTypeValueTable         GTypeValueTable;
struct _GTypeValueTable
{
  void     (*value_init)         (GValue       *value);
  void     (*value_free)         (GValue       *value);
  void     (*value_copy)         (const GValue *src_value,
                                  GValue       *dest_value);
  /* varargs functionality (optional) */
  gpointer (*value_peek_pointer) (const GValue *value);
  gchar            *collect_format;
  gchar*   (*collect_value)      (GValue       *value,
                                  guint         n_collect_values,
                                  GTypeCValue  *collect_values,
                                  guint                collect_flags);
  gchar            *lcopy_format;
  gchar*   (*lcopy_value)        (const GValue *value,
                                  guint         n_collect_values,
                                  GTypeCValue  *collect_values,
                                  guint                collect_flags);
};

有趣的是,你同样不需要详细指定一个value_table在注册过程中,因为value_tables一般从非基本类型的父类中继承,这意味着除非你想写一个基本类型,否则你将不需要提供一个新的value_table因为它可以从父类继承value_table。

请注意,另外一个注册函数是g_type_register_dynamic。我们将不讨论这个函数,因为它与_static版本非常相似。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值