学习GStreamer过程中,有很多基本对象是通过 G_TYPE_BOXED 宏进行定义的。所以我们在GObject库学习过程中,很有必要对此做一下总结。

1 结构体封装对象特点

G_DEFINE_BOXED_TYPE` 在 GObject 系统中是一个宏,用于定义新的 “boxed type” 。GObject 的 boxed types 用于处理纯旧数据(POD)结构,这些数据类型如结构体或联合体,并使其与 GObject 类型系统兼容。

定义了 boxed type 后,你可以在 GObject 系统中,例如在 GValue 或信号中,使用这些类型。

  1. 这类型对象没有信号,属性,引用计数等GObject具有的特性。

  2. GBoxed不区分实例和类结构体,只有一个结构体定义。

  3. 这类型不会自动注释到类型系统(需要调用my_struct_get_type()函数),不能使用g_object_new。不会自动调用free函数。

2 G_DEFINE_BOXED_TYPE 宏

使用 G_DEFINE_BOXED_TYPE 示例程序和宏展开在 /assets/GObjectStudy/202311/12_GBoxed/

定义宏有两个,一个是 G_DEFINE_BOXED_TYPE ,另一个是 G_DEFINE_BOXED_TYPE_WITH_CODE。下面是 G_DEFINE_BOXED_TYPE_WITH_CODE 宏展开:

/*************G_DEFINE_BOXED_TYPE_WITH_CODE (MyStruct, my_struct, my_struct_copy, my_struct_free, g_print("hello\n"));****************展开********************************/

static GType my_struct_get_type_once (void); 
GType my_struct_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 = my_struct_get_type_once (); 
        (__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; 
} __attribute__ ((__noinline__)) 

static GType my_struct_get_type_once (void) { 
  GType (* _g_register_boxed) (const gchar *, 
                               union { MyStruct * (*do_copy_type) (MyStruct *); 
                                       MyStruct * (*do_const_copy_type) (const MyStruct *); 
                                       GBoxedCopyFunc do_copy_boxed; } 
                               __attribute__((__transparent_union__)), 
                               union { void (* do_free_type) (MyStruct *); GBoxedFreeFunc do_free_boxed; } 
                               __attribute__((__transparent_union__)) ) = g_boxed_type_register_static; 
                               
  GType g_define_type_id = _g_register_boxed (g_intern_static_string ("MyStruct"), my_struct_copy, my_struct_free); 
  
  { {g_print("hello\n");} } /* _WITH_CODE插入部分 */
  
  return g_define_type_id; 
};

/*************G_DEFINE_BOXED_TYPE_WITH_CODE (MyStruct, my_struct, my_struct_copy, my_struct_free, g_print("hello\n"));****************展开结束********************************/

  不难发现,关键函数是 g_boxed_type_register_static,该函数的定义如下:

GType
g_boxed_type_register_static (const gchar   *name,
			      GBoxedCopyFunc boxed_copy,
			      GBoxedFreeFunc boxed_free)
{
  static const GTypeValueTable vtable = {
    boxed_proxy_value_init,
    boxed_proxy_value_free,
    boxed_proxy_value_copy,
    boxed_proxy_value_peek_pointer,
    "p",
    boxed_proxy_collect_value,
    "p",
    boxed_proxy_lcopy_value,
  };
  GTypeInfo type_info = {
    0,			/* class_size */
    NULL,		/* base_init */
    NULL,		/* base_finalize */
    NULL,		/* class_init */
    NULL,		/* class_finalize */
    NULL,		/* class_data */
    0,			/* instance_size */
    0,			/* n_preallocs */
    NULL,		/* instance_init */
    &vtable,		/* value_table */
  };
  GType type;

  g_return_val_if_fail (name != NULL, 0);
  g_return_val_if_fail (boxed_copy != NULL, 0);
  g_return_val_if_fail (boxed_free != NULL, 0);
  g_return_val_if_fail (g_type_from_name (name) == 0, 0);

  type = g_type_register_static (G_TYPE_BOXED, name, &type_info, 0);

  /* install proxy functions upon successful registration */
  if (type)
    _g_type_boxed_init (type, boxed_copy, boxed_free);

  return type;
}

使用的也是 g_type_register_static 函数,由于 GTypeInfo结构体全为空,所以也印证了前面的特性

  1. 不能使用 g_object_new 函数创建对象,没有实例和类结构体。只能自定义创建对象函数,实现对象创建,内存分配。

  2. 没有初始化函数和free函数自动调用。

  3. 仅仅就是给类型系统注册了一个类型。