GLib Intro - G_DEFINE_TYPE and g_object_new
1. G_DEFINE_TYPE
#define G_DEFINE_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {})
#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()
2. 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()
3. _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) \
4. _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 GType type_name##_get_type_once (void); \
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;
5. _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 = type_name##_get_type_once (); \
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_GNUC_NO_INLINE \
static GType \
type_name##_get_type_once (void) \
{ \
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 */
6. _G_DEFINE_TYPE_EXTENDED_END
#define _G_DEFINE_TYPE_EXTENDED_END() \
/* following custom code */ \
} \
return g_define_type_id; \
} /* closes type_name##_get_type_once() */
#define G_IMPLEMENT_INTERFACE(TYPE_IFACE, iface_init) { \
const GInterfaceInfo g_implement_interface_info = { \
(GInterfaceInitFunc)(void (*)(void)) iface_init, NULL, NULL \
}; \
g_type_add_interface_static (g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \
}
#define gst_x264_enc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstX264Enc, gst_x264_enc, GST_TYPE_VIDEO_ENCODER,
G_IMPLEMENT_INTERFACE (GST_TYPE_PRESET, NULL));
############################################################################################
############################################################################################
############################################################################################
g_type_register_static_simple (GType parent_type,
const gchar *type_name,
guint class_size,
GClassInitFunc class_init,
guint instance_size,
GInstanceInitFunc instance_init,
GTypeFlags flags)
{
info.class_size = class_size;
info.base_init = NULL;
info.base_finalize = NULL;
info.class_init = class_init;
info.class_finalize = NULL;
info.class_data = NULL;
info.instance_size = instance_size;
info.n_preallocs = 0;
info.instance_init = instance_init;
info.value_table = NULL;
return g_type_register_static (parent_type, type_name, &info, flags);
}
static void type_name##_class_intern_init (gpointer klass) \
{ \
type_name##_parent_class = g_type_class_peek_parent (klass); \
if (TypeName##_private_offset != 0) \
g_type_class_adjust_private_offset (klass, &TypeName##_private_offset); \
type_name##_class_init ((TypeName##Class*) klass); \
}
static void
type_data_make_W (TypeNode *node,
const GTypeInfo *info,
const GTypeValueTable *value_table)
{
data->instance.class_size = info->class_size;
data->instance.class_init_base = info->base_init;
data->instance.class_finalize_base = info->base_finalize;
data->instance.class_init = info->class_init;
data->instance.class_finalize = info->class_finalize;
data->instance.class_data = info->class_data;
data->instance.class = NULL;
data->instance.init_state = UNINITIALIZED;
data->instance.instance_size = info->instance_size;
}
static void type_class_init_Wm (TypeNode *node, GTypeClass *pclass)
{
if (node->data->class.class_init)
node->data->class.class_init (class, (gpointer) node->data->class.class_data);
}
gpointer g_type_class_ref (GType type)
{
if (!node->data->class.class) /* class uninitialized */
type_class_init_Wm (node, pclass);
}
GTypeInstance* g_type_create_instance (GType type)
{
.............
class = g_type_class_ref (type);
.............
if (pnode->data->instance.instance_init)
{
instance->g_class = pnode->data->instance.class;
pnode->data->instance.instance_init (instance, class);
}
.............
return instance;
}
static GObject*
g_object_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params)
{
GObject *object;
/* create object */
object = (GObject*) g_type_create_instance (type);
.............................
}
static gpointer
g_object_new_internal (GObjectClass *class,
GObjectConstructParam *params,
guint n_params)
{
GObjectNotifyQueue *nqueue = NULL;
GObject *object;
if G_UNLIKELY (CLASS_HAS_CUSTOM_CONSTRUCTOR (class))
return g_object_new_with_custom_constructor (class, params, n_params);
object = (GObject *) g_type_create_instance (class->g_type_class.g_type);
..............
}
GObject *
g_object_new_with_properties (GType object_type,
guint n_properties,
const char *names[],
const GValue values[])
{
GObjectClass *class, *unref_class = NULL;
GObject *object;
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
/* Try to avoid thrashing the ref_count if we don't need to (since
* it's a locked operation).
*/
class = g_type_class_peek_static (object_type);
if (class == NULL)
class = unref_class = g_type_class_ref (object_type);
if (n_properties > 0)
{
guint i, count = 0;
GObjectConstructParam *params;
params = g_newa (GObjectConstructParam, n_properties);
for (i = 0; i < n_properties; i++)
{
GParamSpec *pspec;
pspec = g_param_spec_pool_lookup (pspec_pool, names[i], object_type, TRUE);
if (!g_object_new_is_valid_property (object_type, pspec, names[i], params, count))
continue;
params[count].pspec = pspec;
/* Init GValue */
params[count].value = g_newa (GValue, 1);
memset (params[count].value, 0, sizeof (GValue));
g_value_init (params[count].value, G_VALUE_TYPE (&values[i]));
g_value_copy (&values[i], params[count].value);
count++;
}
object = g_object_new_internal (class, params, count);
while (count--)
g_value_unset (params[count].value);
}
else
object = g_object_new_internal (class, NULL, 0);
if (unref_class != NULL)
g_type_class_unref (unref_class);
return object;
}
GObject*
g_object_new_valist (GType object_type,
const gchar *first_property_name,
va_list var_args)
{
GObjectClass *class, *unref_class = NULL;
GObject *object;
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
/* Try to avoid thrashing the ref_count if we don't need to (since
* it's a locked operation).
*/
class = g_type_class_peek_static (object_type);
if (!class)
class = unref_class = g_type_class_ref (object_type);
if (first_property_name)
{
GObjectConstructParam stack_params[16];
GObjectConstructParam *params;
const gchar *name;
gint n_params = 0;
name = first_property_name;
params = stack_params;
do
{
gchar *error = NULL;
GParamSpec *pspec;
pspec = g_param_spec_pool_lookup (pspec_pool, name, object_type, TRUE);
if (!g_object_new_is_valid_property (object_type, pspec, name, params, n_params))
break;
if (n_params == 16)
{
params = g_new (GObjectConstructParam, n_params + 1);
memcpy (params, stack_params, sizeof stack_params);
}
else if (n_params > 16)
params = g_renew (GObjectConstructParam, params, n_params + 1);
params[n_params].pspec = pspec;
params[n_params].value = g_newa (GValue, 1);
memset (params[n_params].value, 0, sizeof (GValue));
G_VALUE_COLLECT_INIT (params[n_params].value, pspec->value_type, var_args, 0, &error);
if (error)
{
g_critical ("%s: %s", G_STRFUNC, error);
g_value_unset (params[n_params].value);
g_free (error);
break;
}
n_params++;
}
while ((name = va_arg (var_args, const gchar *)));
object = g_object_new_internal (class, params, n_params);
while (n_params--)
g_value_unset (params[n_params].value);
if (params != stack_params)
g_free (params);
}
else
/* Fast case: no properties passed in. */
object = g_object_new_internal (class, NULL, 0);
if (unref_class)
g_type_class_unref (unref_class);
return object;
}
gpointer
g_object_new (GType object_type,
const gchar *first_property_name,
...)
{
GObject *object;
va_list var_args;
/* short circuit for calls supplying no properties */
if (!first_property_name)
return g_object_new_with_properties (object_type, 0, NULL, NULL);
va_start (var_args, first_property_name);
object = g_object_new_valist (object_type, first_property_name, var_args);
va_end (var_args);
return object;
}
posted on 2019-11-01 16:12 fanbird2008 阅读(352) 评论(0) 收藏 举报
浙公网安备 33010602011771号