对象的实现
下面的代码实现了上面的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部分。
本文详细解析了如何使用GType系统在C语言中实现对象,通过定义类和实例,初始化函数以及注册类型的过程,展示了创建和管理对象的基本步骤。重点介绍了GTypeInfo结构及其各成员的作用,以及g_object_new函数的使用方法。
868

被折叠的 条评论
为什么被折叠?



