对象的实现
下面的代码实现了上面的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) { boy->age = age; } char *boy_get_name(Boy *boy) { return boy->name; } void boy_set_name(Boy *boy, char *name) { boy->name = name; } Boy* boy_new_with_name(gchar *name) { Boy* boy; boy = boy_new(); boy_set_name(boy, name); return boy; } Boy* boy_new_with_age(gint age) { Boy* boy; boy = boy_new(); boy_set_age(boy, age); return boy; } Boy *boy_new_with_name_and_age(gchar *name, gint age) { Boy *boy; boy = boy_new(); boy_set_name(boy,name); boy_set_age(boy,age); return boy; } static void boy_cry (void) { g_print("The Boy is crying ....../n"); } static void boy_born(void) { g_print("Message : A boy was born ./n"); } void boy_info(Boy *boy) { g_print("The Boy name is %s/n", boy->name); g_print("The Boy age is %d/n", boy->age); }
在这段代码中,出现了实现Boy对象的关键函数,这是在Boy对象的定义中未出现的,也是没必要出现的。
就是两个初始化函数,boy_init和boy_class_init,它们分别用来初始化实例结构和类结构。
它们并不被在代码中明显调用,关键是将其用宏转换为地址指针,然后赋值到GTypeInfo结构中,然后由GType系统自行处理,
同时将它们定义为静态的也是非常必要的。
GTypeInfo结构中定义了对象的类型信息,包括以下内容:
- 包括类结构的长度(必需,即我们定义的BoyClass结构的长度);
- 基础初始化函数(base initialization function,可选);
- 基础结束化函数(base finalization function,可选);
(以上两个函数可以对对象使用的内存来做分配和释放操作,使用时要用GBaseInitFunc和GBaseFinalizeFunc来转换为指针,
本例中均未用到,故设为NULL。)
- 类初始化函数(即我们这里的boy_class_init函数,用GclassInit宏来转换,可选,仅用于类和实例类型);
- 类结束函数(可选);
- 实例初始化函数(可选,即我们这里的boy_init函数);
- 最后一个成员是GType变量表(可选)。
定义好GTypeInfo结构后就可以用g_type_register_static函数来注册对象的类型了。
g_type_register_static函数用来注册对象的类型,它的第一个参数是表示此对象的父类的对象类型,我们这里是G_TYPE_OBJECT,
这个宏用来表示GObject的父类;第二个参数表示此对象的名称,这里为"Boy";第三个参数是此对象的GTypeInfo结构型指针,
这里赋值为&boyinfo;第四个参数是对象注册成功后返回此对象的整型ID标识。
g_object_new函数,用来创建一个基于G_OBJECT的对象,它可以有多个参数,第一个参数是上面说到的已注册的对象标识ID;
第二个参数表示后面参数的数量,如果为0,则没有第三个参数;第三个参数开始类型都是GParameter类型,它也是一个结构型,
定义为:
struct GParameter{
const gchar* name; GValue value; };关于GValue,它是变量类型的统一定义,它是基础的变量容器结构,用于封装变量的值和变量的类型,可以GOBJECT文档的GVALUE部分。