当前位置:操作系统 > Unix/Linux >>

GObject对象系统

内容:

  前言

  类型(GType)与对象(GObject)

  对象的定义

  对象的实现

  信号的定义和应用

  对象的属性和方法

  对象的继承

  测试我们定义的对象

  感谢

  参考资料

  关于作者

  对于本文的评价

  相关内容:

  浅析 GLib

  在 Linux 专区还有:

  教程

  工具与产品

  代码与组件

  项目

  文章

  宋国伟 (gwsong52@sohu.com) 乡村小学英语教师

  2003 年 8 月

  简单的说,GObject对象系统是一个建立在GLIB基础上的,用C语言完成的,具有跨平台特色的、灵活的、可扩展的、非常容易映射到其它语言的面向对象的框架。如果你是一个C语言的执着的追随者,你没有理由不研究一下它。

  前言

  大多数现代的计算机语言都带有自己的类型和对象系统,并附带算法结构。正象GLib提供的基本类型和算法结构(如链表、哈希表等)一样,GObject的对象系统提供了一种灵活的、可扩展的、并容易映射(到其它语言)的面向对象的C语言框架。它的实质可以概括为:

  * 一个通用类型系统,用来注册任意的、轻便的、单根继承的、并能推导出任意深度的结构类型的界面,它照顾组合对象的定制、初始化和内存管理,类结构,保持对象的父子关系,处理这些类型的动态实现。也就是说,这些类型的实现是在运行时重置和卸载的;

  * 一个基本类型的实现集,如整型,枚举型和结构型等;

  * 一个基本对象体系之上的基本对象类型的实现的例子--GObject基本类型;

  * 一个信号系统,允许用户非常灵活的自定义虚的或重载对象的方法,并且能充当非常有效力的通知机制;

  * 一个可扩展的参数/变量体系,支持所有的能被用作处理对象属性或其它参数化类型的基本的类型。

  类型(GType)与对象(GObject)

  GLib中最有特色的是它的对象系统--GObject System,它是以Gtype为基础而实现的一套单根继承的C语言的面向对象的框架。

  GType 是GLib 运行时类型认证和管理系统。GType API 是GObject的基础系统,所以理解GType是理解GObject的关键。Gtype提供了注册和管理所有基本数据类型、用户定义对象和界面类型的技术实现。(注意:在运用任一GType和GObject函数之前必需运行g_type_init()函数来初始化类型系统。)

  为实现类型定制和注册这一目的,所有类型必需是静态的或动态的这二者之一。静态的类型永远不能在运行时加载或卸载,而动态的类型则可以。静态类型由 g_type_register_static()创建,通过GTypeInfo结构来取得类型的特殊信息。动态类型则由 g_type_register_dynamic()创建,用GTypePlugin结构来取代GTypeInfo,并且还包括 g_type_plugin_*()系列API。这些注册函数通常只运行一次,目的是取得它们返回的专有类的类型标识。

  还可以用g_type_register_fundamental来注册基础类型,它同时需要GTypeInfo和GTypeFundamentalInfo两个结构,事实上大多数情况下这是不必要的,因为系统预先定义的基础类型是优于用户自定义的。

  (本文重点介绍创建和使用静态的类型。)

  对象的定义

  在GObject系统中,对象由三个部分组成:

  1. 对象的ID标识(唯一,无符号长整型,所有此类对象共同的标识);

  2. 对象的类结构(唯一,结构型,由对象的所有实例共同拥有);

  3. 对象的实例(多个,结构型,对象的具体实现)。

  基于GObject的对象到底是什么样的呢?下面是基于GObject的简单对象 -- Boy的定义代码:

  /* boy.h */

  #ifndef __BOY_H__

  #define __BOY_H__

  #include <glib-object.h>

  #define BOY_TYPE (boy_get_type())

  #define BOY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),BOY_TYPE,Boy))

  typedef struct _Boy Boy;

  typedef struct _BoyClass BoyClass;

  struct _Boy {

  GObject parent;

  //

  gint age;

  gchar *name;

  void (*cry)(void);

  };

  struct _BoyClass {

  GObjectClass parent_class;

  //

  void (*boy_born)(void);

  };

  GTypeboy_get_type(void);

  Boy* boy_new(void);

  intboy_get_age(Boy *boy);

  voidboy_set_age(Boy *boy, int age);

  char* boy_get_name(Boy *boy);

  voidboy_set_name(Boy *boy, char *name);

  Boy* boy_new_with_name(gchar *name);

  Boy* boy_new_with_age(gint age);

  Boy* boy_new_with_name_and_age(gchar *name, gint age);

  void boy_info(Boy *boy);

  #endif /* __BOY_H__*/

  这是一段典型的C语言头文件定义,包括编译预处理,宏定义,数据结构定义和函数声明;首先要看的是两个数据结构对象Boy和BoyClass,

  结构类型_Boy是Boy对象的实例,就是说我们每创建一个Boy对象,也就同时创建了一个Boy结构。Boy对象中的parent表示此对象的父类, GObject系统中所有对象的共同的根都是GObject类,所以这是必须的;其它的成员可以是公共的,这里包括表示年龄的age,表示名字的name 和表示方法的函数指针cry,外部代码可以操作或引用它们。

  结构类型_BoyClass是Boy对象的类结构,它是所有 Boy对象实例所共有的。BoyClass中的parent_class是GObjectClass,同GObject是所有对象的共有的根一样, GObejctClass是所有对象的类结构的根。在BoyClass中我们还定义了一个函数指针boy_born,也就是说这一函数指针也是所有Boy 对象实例共有的,所有的Boy实例都可以调用它;同样,如果需要的话,你也可以在类结构中定义其它数据成员。

  其余的函数定义包括三种,一种是取得Boy对象的类型ID的函数boy_get_type,这是必须有的;另一种是创建Boy对象实例的函数boy_new和 boy_new_with_*,这是非常清晰明了的创建对象的方式,当然你也可以用g_object_new函数来创建对象;第三种是设定或取得Boy对象属性成员的值的函数boy_get_*和boy_set_*。正常情况下这三种函数都是一个对象所必需的,另外一个函数boy_info用来显示此对象的当前状态。

  宏在GObject系统中用得相当广泛,也相当重要,这里我们定义了两个非常关键的宏,BOY_TYPE宏封装了boy_get_type函数,可以直接取得并替代Boy对象的ID标识;BOY(obj)宏是 G_TYPE_CHECK_INSTANCE_CAST宏的再一次封装,目的是将一个Gobject对象强制转换为Boy对象,这在对象的继承中十分关键,也经常用到。

  对象的实现

  下面的代码实现了上面的Boy对象的定义:

  /* boy.c */

  #include "boy.h"

  enum { BOY_BORN, LAST_SIGNAL };

  static gint boy_signals[LAST_SIGNAL] = { 0 };

  static void boy_cry (void);

  static void boy_born(void);

  static void boy_init(Boy *boy);

  static void boy_class_init(BoyClass *boyclass);

  GType boy_get_type(void)

  {

  static GType boy_type = 0;

  if(!boy_type)

  {

  static const GTypeInfo boy_info = {

  sizeof(BoyClass),

  NULL,NULL,

  (GClassInitFunc)boy_class_init,

  NULL,NULL,

  sizeof(Boy),

  0,

  (GInstanceInitFunc)boy_init

  };

  boy_type = g_type_register_static(G_TYPE_OBJECT,"Boy",&boy_info,0);

  }

  return boy_type;

  }

  static void boy_init(Boy *boy)

  {

  boy->age = 0;

  boy->name = "none";

  boy->cry = boy_cry;

  }

  static void boy_class_init(BoyClass *boyclass)

  {

  boyclass->boy_born = boy_born;

  boy_signals[BOY_BORN] = g_signal_new("boy_born",

  BOY_TYPE,

  G_SIGNAL_RUN_FIRST,

  G_STRUCT_OFFSET(BoyClass,boy_born),

  NULL,NULL,

  g_cclosure_marshal_VOID__VOID,

  G_TYPE_NONE, 0, NULL);

  }

  Boy *boy_new(void)

  {

  Boy *boy;

  boy = g_object_new(BOY_TYPE, NULL);

  g_signal_emit(boy,boy_signals[BOY_BORN],0);

  return boy;

  }

  int boy_get_age(Boy *boy)

  {

  return boy->age;

  }

  void boy_set_age(Boy *boy, int age)

  {
<
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,