十一、接口补充
九、接口 已经讲了接口的一些知识,我在这里对接口进行补充一下。
接口的总结不放到第十节讲的原因是,这已经不是一个标准对象的相关声明与定义宏。我这里讲的标准对象是具有类结构体和实例结构体,而且具备引用计数等特性。而接口具有以下特点。
1 接口结构体定义
只有接口结构体定义(结构结构体可以理解成前几章讲的类结构(或者抽象类)),没有实例结构体,也就是实例结构体就不定义和注册。
/* 接口结构体定义 */
struct _TComparableInterface {
GTypeInterface parent;
/* signal */
void (*arg_error) (TComparable *self);
/* virtual function */
int (*cmp) (TComparable *self, TComparable *other);
};
struct _GTypeInterface {
GType g_type; /* 接口对象的类型注册ID */
GType g_instance_type; /* 添加到那个GObject对象,这就是那个类型GObject对象的ID */
};
这里有两点要注意:
-
接口结构体定义名称是
对象名+Interface
。例如:TComparable + Interface
。 -
接口结构体的第一个成员是
GTypeInterface
,也可以把接口看成为GObject一样的一个基类,这个基类(接口对象)未来要被附加到其他GObject中,所以第一个成员变量仅仅就是记录类型ID。并不是其他对象的类结构体。
GObject 和 GObjectClass 的结构体定义如下,他们除了第一个成员是注册类型ID信息外,还有其他附加信息。接口也是,可以根据需求添加其他成员。
struct _GObjectClass {
GTypeClass g_type_class;
...
};
struct _GTypeClass {
GType g_type;
};
struct _GObject {
GTypeInstance g_type_instance;
guint ref_count;
GData *qdata;
};
struct _GTypeInstance {
GTypeClass *g_class;
};
2 G_DECLARE_INTERFACE 宏
这是接口声明和定义宏展开文件 /assets/GObjectStudy/202311/11_GObjectInterface/interface.i
#define T_TYPE_COMPARABLE (t_comparable_get_type ())
G_DECLARE_INTERFACE (TComparable, t_comparable, T, COMPARABLE, GObject)
struct _TComparableInterface {
GTypeInterface parent;
/* signal */
void (*arg_error) (TComparable *self);
/* virtual function */
int (*cmp) (TComparable *self, TComparable *other);
};
G_DEFINE_INTERFACE (TComparable, t_comparable, G_TYPE_OBJECT)
以下是 G_DECLARE_INTERFACE (TComparable, t_comparable, T, COMPARABLE, GObject)
宏展开:
/************************************G_DECLARE_INTERFACE宏展开*********************START**********************/
GType t_comparable_get_type (void);
typedef struct _TComparable TComparable;
typedef struct _TComparableInterface TComparableInterface;
typedef TComparable *TComparable_autoptr;
typedef GList *TComparable_listautoptr;
typedef GSList *TComparable_slistautoptr;
typedef GQueue *TComparable_queueautoptr;
static __attribute__ ((__unused__)) inline void
glib_autoptr_clear_TComparable (TComparable *_ptr) {
if (_ptr) (glib_autoptr_clear_GObject) ((GObject *) _ptr);
}
static __attribute__ ((__unused__)) inline void
glib_autoptr_cleanup_TComparable (TComparable **_ptr) {
glib_autoptr_clear_TComparable (*_ptr);
}
static __attribute__ ((__unused__)) inline void
glib_listautoptr_cleanup_TComparable (GList **_l) {
g_list_free_full (*_l, (GDestroyNotify) (void(*)(void)) glib_autoptr_clear_GObject);
}
static __attribute__ ((__unused__)) inline void
glib_slistautoptr_cleanup_TComparable (GSList **_l) {
g_slist_free_full (*_l, (GDestroyNotify) (void(*)(void)) glib_autoptr_clear_GObject);
}
static __attribute__ ((__unused__)) inline void
glib_queueautoptr_cleanup_TComparable (GQueue **_q) {
if (*_q) g_queue_free_full (*_q, (GDestroyNotify) (void(*)(void)) glib_autoptr_clear_GObject);
}
__attribute__ ((__unused__)) static inline TComparable *
T_COMPARABLE (gpointer ptr) {
return (((TComparable*) (void *) g_type_check_instance_cast ((GTypeInstance*) (ptr), (t_comparable_get_type ()))));
}
__attribute__ ((__unused__)) static inline gboolean
T_IS_COMPARABLE (gpointer ptr) {
return ((__extension__ ({ GTypeInstance *__inst = (GTypeInstance*) (ptr);
GType __t = (t_comparable_get_type ());
gboolean __r;
if (!__inst) __r = (0);
else if (__inst->g_class && __inst->g_class->g_type == __t) __r = (!(0));
else __r = g_type_check_instance_is_a (__inst, __t); __r; })));
}
__attribute__ ((__unused__)) static inline TComparableInterface *
T_COMPARABLE_GET_IFACE (gpointer ptr) {
return (((TComparableInterface*) g_type_interface_peek (((GTypeInstance*) (ptr))->g_class, (t_comparable_get_type ()))));
}
/************************************G_DECLARE_INTERFACE宏展开*********************END**********************/
-
声明 GType t_comparable_get_type (void);
-
定义 typedef struct _TComparableInterface TComparableInterface
-
定义 T_COMPARABLE()宏。它将一个实例转换为TComparable类型。
-
定义 T_IS_COMPARABLE()宏。它检查实例的类型是否为T_TYPE_COMPARABLE。
-
定义 T_COMPARABLE_GET_IFACE()宏。它获取给定作为参数的实例的接口。
3 G_DEFINE_INTERFACE 宏
/************************************G_DEFINE_INTERFACE宏展开*********************START**********************/
static void t_comparable_default_init (TComparableInterface *klass);
GType t_comparable_get_type (void) {
static gsize static_g_define_type_id = 0;
if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false");
(void) (0 ? (gpointer) *(&static_g_define_type_id) : ((void *)0));
(!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false");
__typeof__ (*(&static_g_define_type_id)) gapg_temp_newval;
__typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id);
__atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5);
gapg_temp_newval;
})) && g_once_init_enter (&static_g_define_type_id));
}))) {
GType g_define_type_id = g_type_register_static_simple (((GType) ((2) << (2))),
g_intern_static_string ("TComparable"),
sizeof (TComparableInterface),
(GClassInitFunc)(void (*)(void)) t_comparable_default_init,
0,
(GInstanceInitFunc) ((void *)0),
(GTypeFlags) 0);
if (((GType) ((20) << (2))) != ((GType) ((0) << (2))))
g_type_interface_add_prerequisite (g_define_type_id, ((GType) ((20) << (2))));
{ {;;} }
(__extension__ ({
_Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false");
0 ? (void) (*(&static_g_define_type_id) = (g_define_type_id)) : (void) 0; g_once_init_leave ((&static_g_define_type_id), (gsize) (g_define_type_id));
}));
}
return static_g_define_type_id;
}
/************************************G_DEFINE_INTERFACE宏展开*********************END**********************/
g_type_register_static_simple
调用的时候,函数参数第一个是 G_TYPE_INTERFACE
,没有实例结构体相关的参数。
4 接口使用
其他继承于GObject对象使用的时候,使用 G_IMPLEMENT_INTERFACE (T_TYPE_COMPARABLE, t_comparable_interface_init)
。其实就是给继承于GObject的对象添加了一个接口静态区域。
以下是 ` G_IMPLEMENT_INTERFACE (T_TYPE_COMPARABLE, t_comparable_interface_init) `宏展开:
/* G_IMPLEMENT_INTERFACE 宏展开 */
const GInterfaceInfo comparable_info = {
(GInterfaceInitFunc) t_comparable_interface_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
g_type_add_interface_static (T_TYPE_INT, T_TYPE_COMPARABLE, &comparable_info);