二、GObject子类对象的私有属性模拟
1.1 PMDList类头文件
/* file name : pm-dlist.h */
#ifndef PM_DLIST_H
#define PM_DLIST_H
#include <glib-object.h>
/**
* 通过该宏指向的pm_dlist_get_type函数
* 可以获得PMDList类结构体信息和初始化函数
* pm_dlist_get_type函数内部的实现由G_DEFINE_TYPE宏实现
*/
#define PM_TYPE_DLIST (pm_dlist_get_type ())
typedef struct _PMDList PMDList;
struct _PMDList {
GObject parent_instance;
};
typedef struct _PMDListClass PMDListClass;
struct _PMDListClass {
GObjectClass parent_class;
};
GType pm_dlist_get_type (void);
#endif
分析
typedef struct _PMDList PMDList;
struct _PMDList {
GObject parent_instance;
};
只保留了父类成员,其他变量移到C文件中,可以数据隐藏。这本章节加入了私有属性隐藏,其实PMDList类已经是由三个结构体组成的PMDList实例结构体,PMDListClass类结构体,下文中马上提到的PMDListPrivate私有属性结构体。至于私有属性结构体,怎样加入到PMDList类中,下文讲到。
1.2 PMDList类函数
/* file name : pm-dlist.c */
#include "pm-dlist.h"
G_DEFINE_TYPE (PMDList, pm_dlist, G_TYPE_OBJECT);
#define PM_DLIST_GET_PRIVATE(obj) (\
G_TYPE_INSTANCE_GET_PRIVATE ((obj), PM_TYPE_DLIST, PMDListPrivate))
typedef struct _PMDListNode PMDListNode;
struct _PMDListNode {
PMDListNode *prev;
PMDListNode *next;
void *data;
};
typedef struct _PMDListPrivate PMDListPrivate;
struct _PMDListPrivate {
PMDListNode *head;
PMDListNode *tail;
};
static void
pm_dlist_class_init (PMDListClass *klass)
{
g_type_class_add_private (klass, sizeof (PMDListPrivate));
}
static void
pm_dlist_init (PMDList *self)
{
PMDListPrivate *priv = PM_DLIST_GET_PRIVATE (self);
priv->head = 0x3333;
priv->tail = 0x2222;
}
分析 私有成员结构体PMDListPrivate可以通过PM_DLIST_GET_PRIVATE(obj)宏获取PMDList对象的head与tail指针。但是,那个PMDListPrivate结构体是怎样被添加到PMDList对象中的呢?答案存在于PMDList类的类结构体初始化函数之中,如下:
static void
pm_dlist_class_init (PMDListClass *klass)
{
g_type_class_add_private (klass, sizeof (PMDListPrivate));
}
所以,在类初始化的时候,因为类初始化函数只会运行一次且,比pm_dlist_init函数先运行。g_object_new函数调用,GObject库的类型管理系统可以从pm_dlist_clss_init函数中获知PMDListPrivate结构体所占用的存储空间,便会多分出一部分以容纳PMDListPrivate结构体,这样便相当于将一个PMDListPrivate结构体挂到PMDList对象之中。 GObject 库对私有属性所占用的存储空间是由限制的。一个 GObject 子类对象,它的私有属性及其父类对象的私有属性累加起来不能超过 64 KB。
1.3 MAIC函数
#include "pm-dlist.h"
int
main (void)
{
/* GObject 库的类型管理系统的初始化 */
g_type_init ();
PMDList *list;
list = g_object_new (PM_TYPE_DLIST, NULL);
g_object_unref (list);
return 0;
}
总结
- 类头文件的实例结构体私有成员,隐藏在类C文件中,重新命令一个新的私有属性结构体。该私有属性结构体成员可以通过宏PM_DLIST_GET_PRIVATE(obj)构建PMDList和 PMDListPrivate的联系。即可以通过该宏访问私有属性内部成员。
- PMDListPrivate是由类初始化函数添加到PMDList类,并在此时分配内存空间。我们可以通过PM_DLIST_GET_PRIVATE获得该内存空间地址,修改成员变量。
- 如果在类C文件下面创建函数,都是可以访问私有熟悉成员的。
上述的子对象私有属性,私有属性是添加到的是类对象,所以创建两个PMList对象,两个的PMList私有结构体地址是相同的
#include "pm-dlist.h"
int
main (void) {
PMDList *list1, *list2;
list1 = g_object_new (PM_TYPE_DLIST, NULL);
list2 = g_object_new (PM_TYPE_DLIST, NULL);
PMDListPrivate *list1_priv = PM_DLIST_GET_PRIVATE (list1);
PMDListPrivate *list2_priv = PM_DLIST_GET_PRIVATE (list1);
g_print ("list1_priv address = %p\n", list1_priv);
g_print ("list2_priv address = %p\n", list2_priv);
g_object_unref (list1);
g_object_unref (list2);
return 0;
}
输出结果如下
list1_priv address = 0x56203f502800 list2_priv address = 0x56203f502800
补充(Oct-26-2023)
-
g_type_class_add_private在2.58版本以后不赞成使用。
-
推荐使用G_DEFINE_TYPE_WITH_PRIVATE宏(给实例添加私有成员)。