十二、GBoxed类型
学习GStreamer过程中,有很多基本对象是通过 G_TYPE_BOXED
宏进行定义的。所以我们在GObject库学习过程中,很有必要对此做一下总结。
1 结构体封装对象特点
G_DEFINE_BOXED_TYPE
` 在 GObject 系统中是一个宏,用于定义新的 “boxed type” 。GObject 的 boxed types 用于处理纯旧数据(POD)结构,这些数据类型如结构体或联合体,并使其与 GObject 类型系统兼容。
定义了 boxed type 后,你可以在 GObject 系统中,例如在 GValue 或信号中,使用这些类型。
-
这类型对象没有信号,属性,引用计数等GObject具有的特性。
-
GBoxed不区分实例和类结构体,只有一个结构体定义。
-
这类型不会自动注释到类型系统(需要调用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
结构体全为空,所以也印证了前面的特性
-
不能使用 g_object_new 函数创建对象,没有实例和类结构体。只能自定义创建对象函数,实现对象创建,内存分配。
-
没有初始化函数和free函数自动调用。
-
仅仅就是给类型系统注册了一个类型。