九、接口 已经讲了接口的一些知识,我在这里对接口进行补充一下。

接口的总结不放到第十节讲的原因是,这已经不是一个标准对象的相关声明与定义宏。我这里讲的标准对象是具有类结构体和实例结构体,而且具备引用计数等特性。而接口具有以下特点。

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 */
};

这里有两点要注意:

  1. 接口结构体定义名称是对象名+Interface。例如:TComparable + Interface

  2. 接口结构体的第一个成员是 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);