G_DEFINE_TYPE分解
G_DEFINE_TYPE
是一个用于类型实现的宏,它声明了一个类的初始化函数,一个实例的初始化函数(关于这些的信息请参考gtype.h)和一个名为type_name##_parent_class
的静态变量,指向父类。此外,它还定义了一个type_name##_get_type()
函数。
G_DEFINE_TYPE是由_G_DEFINE_TYPE_EXTENDED_BEGIN
,_G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
,_G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
三个组成,这三个又可以展开为好多个宏,到最后会产生好多代码,其中就有type_name##_get_type()
,比如curlhttpsink插件,就是gst_curl_http_sink_get_type()
,下面就以curlhttpsink带入分析:
G_DEFINE_TYPE (GstCurlHttpSink, gst_curl_http_sink, GST_TYPE_CURL_TLS_SINK);
// TN: GstCurlHttpSink // The name of the new type,展开后是作为函数的参数TypeName
// t_n: gst_curl_http_sink // The name of the new type, in lowercase, with words,展开后是函数名的一部分type_name
// T_P: GST_TYPE_CURL_TLS_SINK // The #GType of the parent type. 展开后指向get_type函数
G_DEFINE_TYPE的宏展开次序:
G_DEFINE_TYPE
G_DEFINE_TYPE_EXTENDED
_G_DEFINE_TYPE_EXTENDED_BEGIN
_G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
_G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
_G_DEFINE_TYPE_EXTENDED_END
下面是每一个的定义:
G_DEFINE_TYPE:
// G_DEFINE_TYPE
#define G_DEFINE_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {})
G_DEFINE_TYPE_EXTENDED:
#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
_G_DEFINE_TYPE_EXTENDED_BEGIN & _G_DEFINE_TYPE_EXTENDED_END:
//_G_DEFINE_TYPE_EXTENDED_BEGIN
#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \
_G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \
_G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
//_G_DEFINE_TYPE_EXTENDED_END
#define _G_DEFINE_TYPE_EXTENDED_END() \
/* following custom code */ \
} \
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
} \
return g_define_type_id__volatile; \
} /* closes type_name##_get_type() */
_G_DEFINE_TYPE_EXTENDED_BEGIN_PRE:
// _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \
\
static void type_name##_init (TypeName *self); \
static void type_name##_class_init (TypeName##Class *klass); \
static gpointer type_name##_parent_class = NULL; \
static gint TypeName##_private_offset; \
\
_G_DEFINE_TYPE_EXTENDED_CLASS_INIT(TypeName, type_name) \
\
G_GNUC_UNUSED \
static inline gpointer \
type_name##_get_instance_private (TypeName *self) \
{ \
return (G_STRUCT_MEMBER_P (self, TypeName##_private_offset)); \
} \
\
GType \
type_name##_get_type (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0;
/* Prelude goes here */
_G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER:
// _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType g_define_type_id = \
g_type_register_static_simple (TYPE_PARENT, \
g_intern_static_string (#TypeName), \
sizeof (TypeName##Class), \
(GClassInitFunc)(void (*)(void)) type_name##_class_intern_init, \
sizeof (TypeName), \
(GInstanceInitFunc)(void (*)(void)) type_name##_init, \
(GTypeFlags) flags); \
{ /* custom code follows */
再把前面这些放在一块展开就是下面的代码段,可以用下面这curlhttpsink的字符串带入阅读:
- TypeName:GstCurlHttpSink
- type_name:gst_curl_http_sink
- TYPE_PARENT:GST_TYPE_CURL_TLS_SINK
/ _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
static void type_name##_init (TypeName *self); \
static void type_name##_class_init (TypeName##Class *klass); \
static gpointer type_name##_parent_class = NULL; \
static gint TypeName##_private_offset; \
\
_G_DEFINE_TYPE_EXTENDED_CLASS_INIT(TypeName, type_name) \
\
G_GNUC_UNUSED \
static inline gpointer \
type_name##_get_instance_private (TypeName *self) \
{ \
return (G_STRUCT_MEMBER_P (self, TypeName##_private_offset)); \
} \
\
GType \
type_name##_get_type (void) \
{ \
static volatile gsize g_define_type_id__volatile = 0;
/* Prelude goes here */
/ _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
if (g_once_init_enter (&g_define_type_id__volatile)) \
{ \
GType g_define_type_id = \
g_type_register_static_simple (TYPE_PARENT, \
g_intern_static_string (#TypeName), \
sizeof (TypeName##Class), \
(GClassInitFunc)(void (*)(void)) type_name##_class_intern_init, \
sizeof (TypeName), \
(GInstanceInitFunc)(void (*)(void)) type_name##_init, \
(GTypeFlags) flags); \
{ /* custom code follows */
// _C_; G_DEFINE_TYPE_EXTENDED的_C_参数展开
/ _G_DEFINE_TYPE_EXTENDED_END
/* following custom code */ \
} \
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
} \
return g_define_type_id__volatile; \
} /* closes type_name##_get_type() */
G_DEFINE_TYPE_WITH_CODE分解
和G_DEFINE_TYPE
一样,G_DEFINE_TYPE_WITH_CODE
实际上和G_DEFINE_TYPE
基本上是一样的,G_DEFINE_TYPE_WITH_CODE
比起G_DEFINE_TYPE
多了参数_C_
,_C_
是其他的初始化代码,G_DEFINE_TYPE只有3个参数,不能有这部分。
从xvimagesink中可以看到实例:
/// G_DEFINE_TYPE_WITH_CODE
G_DEFINE_TYPE_WITH_CODE (GstXvImageSink, gst_xv_image_sink, GST_TYPE_VIDEO_SINK,
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION,
gst_xv_image_sink_navigation_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY,
gst_xv_image_sink_video_overlay_init);
G_IMPLEMENT_INTERFACE (GST_TYPE_COLOR_BALANCE,
gst_xv_image_sink_colorbalance_init));
G_DEFINE_TYPE_WITH_CODE
vs G_DEFINE_TYPE
/// G_DEFINE_TYPE_WITH_CODE
#define G_DEFINE_TYPE_WITH_CODE(TN, t_n, T_P, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, 0) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
/// G_DEFINE_TYPE & G_DEFINE_TYPE_EXTENDED
#define G_DEFINE_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {})
#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
除了这个_C_
参数之外,其他都是完全一样的,这里就不展开了。