阶段 | 相应API | 作用 | GObject 调用顺序 | GstObject | GstElement |
1 | xxx_yyy_get_type() |
创建TypeNode, 并且赋值一些APIs: base_class_init() class_init() instance_init(), 等等 |
|||
2 | g_type_class_ref() |
调用base_class_init() 从父-->子, |
g_object_base_class_init() |
1. 父类:g_object_base_class_init() 2. 自己没有base_init() |
1. 爷爷:g_object_base_class_init() 2. 父亲没有base_init() 3. gst_element_base_class_init |
调用class_init(), 指定各种APIs 包括class->constructor(), set_property()/get_property() dispose()/finalize() |
g_object_do_class_init() |
gst_object_class_init() 1. 首选取得GObjectClass 2. 重载一些函数 3. 装载一些自己的signal |
gst_element_class_init() 1. 首选取得GObjectClass 2. 把GObjectClass的一些函数换成自己的(重载) 3. 装载自己的信号 |
||
3 | g_object_new() |
调用class->constructor() --> g_type_create_instance() --> 父类的instance(), 自己的instance() |
g_object_constructor()->g_type_create_instance() -> 1. g_object_init() |
g_object_constructor()->g_type_create_instance() -> 1. 父亲:g_object_init() 2.自己:gst_object_init() |
g_object_constructor()->g_type_create_instance() -> 1. 爷爷:g_object_init() 2.父亲:gst_object_init() 3. 自己:gst_element_init()
|
set properties |
1. 这个API完成GObject类型的注册
2. GObject 作为一个基础类型,放入全局数组以及Hash Table中
3. 分配GObject Node的数据,并且把用户指定的一系列函数指针赋值过去
4. 此时还没有真正的GObject对象实例。
1 2 3 4 5 | void g_type_init ( void ) { g_type_init_with_debug_flags (0); } |
1 2 3 | /* G_TYPE_OBJECT */ g_object_type_init (); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | void g_object_type_init ( void ) { static gboolean initialized = FALSE; static const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE, }; static GTypeInfo info = { sizeof (GObjectClass), (GBaseInitFunc) g_object_base_class_init, (GBaseFinalizeFunc) g_object_base_class_finalize, (GClassInitFunc) g_object_do_class_init, NULL /* class_destroy */ , NULL /* class_data */ , sizeof (GObject), 0 /* n_preallocs */ , (GInstanceInitFunc) g_object_init, NULL, /* value_table */ }; static const GTypeValueTable value_table = { g_value_object_init, /* value_init */ g_value_object_free_value, /* value_free */ g_value_object_copy_value, /* value_copy */ g_value_object_peek_pointer, /* value_peek_pointer */ "p" , /* collect_format */ g_value_object_collect_value, /* collect_value */ "p" , /* lcopy_format */ g_value_object_lcopy_value, /* lcopy_value */ }; GType type; g_return_if_fail (initialized == FALSE); initialized = TRUE; /* G_TYPE_OBJECT */ info.value_table = &value_table; type = g_type_register_fundamental (G_TYPE_OBJECT, g_intern_static_string ( "GObject" ), &info, &finfo, 0); g_assert (type == G_TYPE_OBJECT); g_value_register_transform_func (G_TYPE_OBJECT, G_TYPE_OBJECT, g_value_object_transform_value); } |
这里注册GObject类型:
1. 指定这个类型的标记flag
static const GTypeFundamentalInfo finfo = {
G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE,
};
2. 注册Class的GTypeInfo. 相关的几个函数指针
3. 注册GObject type的函数表Value Table
问题来了:
g_object_base_class_init、g_object_do_class_init、g_object_init 何时被调用?
有什么严格的顺序吗?
我们先看看GObject的内部注册过程中,干了些什么?然后再看看基于Gobject生成新的object实例时
做了些什么?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | GType g_type_register_fundamental (GType type_id, const gchar *type_name, const GTypeInfo *info, const GTypeFundamentalInfo *finfo, GTypeFlags flags) { TypeNode *node; G_WRITE_LOCK (&type_rw_lock); node = type_node_fundamental_new_W (type_id, type_name, finfo->type_flags); type_add_flags_W (node, flags); if (check_type_info_I (NULL, NODE_FUNDAMENTAL_TYPE (node), type_name, info)) type_data_make_W (node, info, check_value_table_I (type_name, info->value_table) ? info->value_table : NULL); G_WRITE_UNLOCK (&type_rw_lock); return NODE_TYPE (node); } |
其中关系不大的代码去掉了。
因为GObject是基础类型,没有父节点,所以代码中,去掉了部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | static TypeNode* type_node_any_new_W (TypeNode *pnode, GType ftype, const gchar *name, GTypePlugin *plugin, GTypeFundamentalFlags type_flags) { guint n_supers; GType type; TypeNode *node; guint i, node_size = 0; n_supers = pnode ? pnode->n_supers + 1 : 0; if (!pnode) node_size += SIZEOF_FUNDAMENTAL_INFO; /* fundamental type info */ node_size += SIZEOF_BASE_TYPE_NODE (); /* TypeNode structure */ node_size += ( sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */ node = g_malloc0 (node_size); if (!pnode) /* offset fundamental types */ { node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO); static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node; type = ftype; } node->n_supers = n_supers; if (!pnode) { node->supers[0] = type; node->supers[1] = 0; node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0; node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0; if (NODE_IS_IFACE (node)) { IFACE_NODE_N_PREREQUISITES (node) = 0; IFACE_NODE_PREREQUISITES (node) = NULL; } else _g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node)); } TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type)); node->plugin = plugin; node->n_children = 0; node->children = NULL; node->data = NULL; node->qname = g_quark_from_string (name); node->global_gdata = NULL; g_hash_table_insert (static_type_nodes_ht, GUINT_TO_POINTER (node->qname), (gpointer) type); return node; } |
上面重要的地方:
static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node; //把G_OBJECT_TYPE放入基础类型数组。
node->supers[0] = type; //没有父亲节点
node->supers[1] = 0;
node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0; //可类化
node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0; //可实例化
下面是把前面设置的GObject的标识:存入node的qdata中,用quark:static_quark_type_flags 来标识。
即:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static void type_add_flags_W (TypeNode *node, GTypeFlags flags) { guint dflags; g_return_if_fail ((flags & ~TYPE_FLAG_MASK) == 0); g_return_if_fail (node != NULL); if ((flags & TYPE_FLAG_MASK) && node->is_classed && node->data && node->data-> class . class ) g_warning ( "tagging type `%s' as abstract after class initialization" , NODE_NAME (node)); dflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)); dflags |= flags; type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags)); } |
重点是下面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | /* --- type info (type node data) --- */ static void type_data_make_W (TypeNode *node, const GTypeInfo *info, const GTypeValueTable *value_table) { TypeData *data; GTypeValueTable *vtable = NULL; guint vtable_size = 0; g_assert (node->data == NULL && info != NULL); if (!value_table) { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); if (pnode) vtable = pnode->data->common.value_table; else { static const GTypeValueTable zero_vtable = { NULL, }; value_table = &zero_vtable; } } if (value_table) { /* need to setup vtable_size since we have to allocate it with data in one chunk */ vtable_size = sizeof (GTypeValueTable); if (value_table->collect_format) vtable_size += strlen (value_table->collect_format); if (value_table->lcopy_format) vtable_size += strlen (value_table->lcopy_format); vtable_size += 2; } if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */ { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); data = g_malloc0 ( sizeof (InstanceData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData)); 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; /* We'll set the final value for data->instance.private size * after the parent class has been initialized */ data->instance.private_size = 0; data->instance.class_private_size = 0; if (pnode) data->instance.class_private_size = pnode->data->instance.class_private_size; #ifdef DISABLE_MEM_POOLS data->instance.n_preallocs = 0; #else /* !DISABLE_MEM_POOLS */ data->instance.n_preallocs = MIN (info->n_preallocs, 1024); #endif /* !DISABLE_MEM_POOLS */ data->instance.instance_init = info->instance_init; } else if (node->is_classed) /* only classed */ { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); data = g_malloc0 ( sizeof (ClassData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData)); data-> class .class_size = info->class_size; data-> class .class_init_base = info->base_init; data-> class .class_finalize_base = info->base_finalize; data-> class .class_init = info->class_init; data-> class .class_finalize = info->class_finalize; data-> class .class_data = info->class_data; data-> class . class = NULL; data-> class .class_private_size = 0; if (pnode) data-> class .class_private_size = pnode->data-> class .class_private_size; data-> class .init_state = UNINITIALIZED; } else if (NODE_IS_IFACE (node)) { data = g_malloc0 ( sizeof (IFaceData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData)); data->iface.vtable_size = info->class_size; data->iface.vtable_init_base = info->base_init; data->iface.vtable_finalize_base = info->base_finalize; data->iface.dflt_init = info->class_init; data->iface.dflt_finalize = info->class_finalize; data->iface.dflt_data = info->class_data; data->iface.dflt_vtable = NULL; } else if (NODE_IS_BOXED (node)) { data = g_malloc0 ( sizeof (BoxedData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData)); } else { data = g_malloc0 ( sizeof (CommonData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData)); } node->data = data; if (vtable_size) { gchar *p; /* we allocate the vtable and its strings together with the type data, so * children can take over their parent's vtable pointer, and we don't * need to worry freeing it or not when the child data is destroyed */ *vtable = *value_table; p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable)); p[0] = 0; vtable->collect_format = p; if (value_table->collect_format) { strcat (p, value_table->collect_format); p += strlen (value_table->collect_format); } p++; p[0] = 0; vtable->lcopy_format = p; if (value_table->lcopy_format) strcat (p, value_table->lcopy_format); } node->data->common.value_table = vtable; node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL && !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)))); g_assert (node->data->common.value_table != NULL); /* paranoid */ g_atomic_int_set (( int *) &node->ref_count, 1); } |
这里有个union的变量:node->data: 可选4个类型:BoxedData/IFaceData/ClassData/InsanceData
node->is_instantiatable = 1
所以选择InstanceData
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | if (node->is_instantiatable) /* carefull, is_instantiatable is also is_classed */ { TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); data = g_malloc0 ( sizeof (InstanceData) + vtable_size); if (vtable_size) vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData)); 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; /* We'll set the final value for data->instance.private size * after the parent class has been initialized */ data->instance.private_size = 0; data->instance.class_private_size = 0; if (pnode) data->instance.class_private_size = pnode->data->instance.class_private_size; #ifdef DISABLE_MEM_POOLS data->instance.n_preallocs = 0; #else /* !DISABLE_MEM_POOLS */ data->instance.n_preallocs = MIN (info->n_preallocs, 1024); #endif /* !DISABLE_MEM_POOLS */ data->instance.instance_init = info->instance_init; } |
node->data = data;
把前面class的base/class/instance的APIs, Value Table APIs, 赋值给node->data
g_type_init():
1. ....
2. g_object_type_init()
3. ...
之后应该就是g_object_new?
我们找个例子看看:
GObject
`|_____ GstObject
在gstobject.c:
1 | G_DEFINE_ABSTRACT_TYPE (GstObject, gst_object, G_TYPE_OBJECT); |
先比较一下gobject.c/gstobject.c提供的一些API:
父 | Me (当前) | 儿子 | 孙子 | 重孙子 |
GObject | GstObject | GstElement | GstBin | GstPipeline |
g_object_base_class_init() | gst_element_base_class_init | gst_bin_base_init | gst_pipeline_base_init | |
g_object_do_class_init() | gst_object_class_init() | gst_element_class_init | gst_bin_class_init | gst_pipeline_class_init |
g_object_init() | gst_object_init() | gst_element_init | gst_bin_init | gst_pipeline_init |
把宏展开,看到上面gstobject提供的两个API,绑定了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #define _G_DEFINE_TYPE_EXTENDED_BEGIN(GstObject, gst_object, G_TYPE_OBJECT, flags) \ \ static void gst_object_init (GstObject *self); \ static void gst_object_class_init (GstObjectClass *klass); \ static gpointer gst_object_parent_class = NULL; \ static void gst_object_class_intern_init (gpointer klass) \ { \ gst_object_parent_class = g_type_class_peek_parent (klass); \ gst_object_class_init ((GstObjectlass*) klass); \ } \ \ GType \ gst_object_get_type ( void ) \ { \ static volatile gsize g_define_type_id__volatile = 0; \ if (g_once_init_enter (&g_define_type_id__volatile)) \ { \ GType g_define_type_id = \ g_type_register_static_simple (G_TYPE_OBJECT, \ g_intern_static_string ( "GstObject" ), \ sizeof (CGstObjectClass), \ (GClassInitFunc) gst_object_class_intern_init, \ sizeof (GstObject), \ (GInstanceInitFunc) gst_object_init, \ (GTypeFlags) flags); \ { /* custom code follows */ #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 gst_object_get_type() */ |
首先取得父类的class数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | gpointer g_type_class_peek_parent (gpointer g_class) { TypeNode *node; gpointer class = NULL; g_return_val_if_fail (g_class != NULL, NULL); node = lookup_type_node_I (G_TYPE_FROM_CLASS (g_class)); /* We used to acquire a read lock here. That is not necessary, since * parent->data->class.class is constant as long as the derived class * exists. */ if (node && node->is_classed && node->data && NODE_PARENT_TYPE (node)) { node = lookup_type_node_I (NODE_PARENT_TYPE (node)); class = node->data-> class . class ; } else if (NODE_PARENT_TYPE (node)) g_warning (G_STRLOC ": invalid class pointer `%p'" , g_class); return class ; } |
class = node->data->class.class;
然后真正开始Init:
gst.c中:
1 | g_type_class_ref (gst_object_get_type ()); |
首先会调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | GType 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) { GTypeInfo info; 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); } |
然后指定自己的class_init/Instance_init函数,就开始创建这个TypeNode.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | GType g_type_register_static (GType parent_type, const gchar *type_name, const GTypeInfo *info, GTypeFlags flags) { TypeNode *pnode, *node; GType type = 0; g_return_val_if_type_system_uninitialized (0); g_return_val_if_fail (parent_type > 0, 0); g_return_val_if_fail (type_name != NULL, 0); g_return_val_if_fail (info != NULL, 0); if (!check_type_name_I (type_name) || !check_derivation_I (parent_type, type_name)) return 0; if (info->class_finalize) { g_warning ( "class finalizer specified for static type `%s'" , type_name); return 0; } pnode = lookup_type_node_I (parent_type); G_WRITE_LOCK (&type_rw_lock); type_data_ref_Wm (pnode); if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info)) { node = type_node_new_W (pnode, type_name, NULL); type_add_flags_W (node, flags); type = NODE_TYPE (node); type_data_make_W (node, info, check_value_table_I (type_name, info->value_table) ? info->value_table : NULL); } G_WRITE_UNLOCK (&type_rw_lock); return type; } |
1. type_data_ref_Wm (pnode); //给父节点增加一个引用计数
2. node = type_node_new_W (pnode, type_name, NULL); //从父节点拷贝出一份内存,并且建立父子关系;
并且把新创建的“子节点” 保存在父节点的数组中:pnode->children[i] = type;
3. type_data_make_W, 就是用户指定的各种APIs, Value Table APIs, 指定给这个新建的Type Node, 这里是给GstObject
g_type_class_ref(GstObject);
这个函数是个循环嵌套函数!
1 2 3 4 5 6 7 8 9 10 11 12 13 | gpointer g_type_class_ref (GType type) { TypeNode *node; GType ptype; gboolean holds_ref; GTypeClass *pclass; /* optimize for common code path */ node = lookup_type_node_I (type); /* we need an initialized parent class for initializing derived classes */ ptype = NODE_PARENT_TYPE (node); pclass = ptype ? g_type_class_ref (ptype) : NULL; |
它会顺藤摸瓜!找到最上面的祖先:
这里它会找到GObject (GstObject的父类),GObject已经是最顶层了。
好,接着往下:
1 2 3 4 5 | if (!holds_ref) type_data_ref_Wm (node); if (!node->data-> class . class ) /* class uninitialized */ type_class_init_Wm (node, pclass); |
最关键的地方:如果当前class并没有被初始化,则进行初始化。
先初始化GObject, 然后轮到其儿子:GstObject.
对某个typeclass进行下面的顺序进行初始化:
BASE_CLASS_INIT
BASE_IFACE_INIT
CLASS_INIT
IFACE_INIT
INITIALIZED
对GObject的初始化:
1. BASE_CLASS_INIT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* stack all base class initialization functions, so we * call them in ascending order. */ for (bnode = node; bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode))) { if (bnode->data-> class .class_init_base) init_slist = g_slist_prepend (init_slist, (gpointer) bnode->data-> class .class_init_base); } for (slist = init_slist; slist; slist = slist->next) { GBaseInitFunc class_init_base = (GBaseInitFunc) slist->data; class_init_base ( class ); } |
for (bnode = node; bnode; bnode = lookup_type_nodeI (NODE_PARENT_TYPE (bnode)))
是从最底层往上层循环(孙子 --> 儿子--> 爷爷)
init_slist, 是反过来弄的:
爷爷->儿子-->孙子,这么一个顺序,进行class_init_base()
后面会印证。
2. CLASS_INIT
1 2 3 4 5 6 | g_atomic_int_set (&node->data-> class .init_state, CLASS_INIT); G_WRITE_UNLOCK (&type_rw_lock); if (node->data-> class .class_init) node->data-> class .class_init ( class , (gpointer) node->data-> class .class_data); |
此时执行:g_object_do_class_init()
父类初始化完成后,嵌套退回一层,开始自行GstObjec的初始化:
也是按照那个顺序,有的成员是NULL, 就跳过去:
3. GstObject的CLASS_INIT
1 2 3 4 5 6 | g_atomic_int_set (&node->data-> class .init_state, CLASS_INIT); G_WRITE_UNLOCK (&type_rw_lock); if (node->data-> class .class_init) node->data-> class .class_init ( class , (gpointer) node->data-> class .class_data); |
此时执行:gst_object_class_init()
注意,此时:gobject/gstobject的实例instance对象还没有建立!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | static void g_object_base_class_init (GObjectClass * class ) { GObjectClass *pclass = g_type_class_peek_parent ( class ); /* Don't inherit HAS_DERIVED_CLASS flag from parent class */ class ->flags &= ~CLASS_HAS_DERIVED_CLASS_FLAG; if (pclass) pclass->flags |= CLASS_HAS_DERIVED_CLASS_FLAG; /* reset instance specific fields and methods that don't get inherited */ class ->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL; class ->get_property = NULL; class ->set_property = NULL; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | static void g_object_do_class_init (GObjectClass * class ) { /* read the comment about typedef struct CArray; on why not to change this quark */ quark_closure_array = g_quark_from_static_string ( "GObject-closure-array" ); quark_weak_refs = g_quark_from_static_string ( "GObject-weak-references" ); quark_toggle_refs = g_quark_from_static_string ( "GObject-toggle-references" ); pspec_pool = g_param_spec_pool_new (TRUE); property_notify_context.quark_notify_queue = g_quark_from_static_string ( "GObject-notify-queue" ); property_notify_context.dispatcher = g_object_notify_dispatcher; class ->constructor = g_object_constructor; class ->constructed = g_object_constructed; class ->set_property = g_object_do_set_property; class ->get_property = g_object_do_get_property; class ->dispose = g_object_real_dispose; class ->finalize = g_object_finalize; class ->dispatch_properties_changed = g_object_dispatch_properties_changed; class ->notify = NULL; /** * GObject::notify: * @gobject: the object which received the signal. * @pspec: the #GParamSpec of the property which changed. * * The notify signal is emitted on an object when one of its * properties has been changed. Note that getting this signal * doesn't guarantee that the value of the property has actually * changed, it may also be emitted when the setter for the property * is called to reinstate the previous value. * * This signal is typically used to obtain change notification for a * single property, by specifying the property name as a detail in the * g_signal_connect() call, like this: * |[ * g_signal_connect (text_view->buffer, "notify::paste-target-list", * G_CALLBACK (gtk_text_view_target_list_notify), * text_view) * ]| * It is important to note that you must use * <link linkend="canonical-parameter-name">canonical</link> parameter names as * detail strings for the notify signal. */ gobject_signals[NOTIFY] = g_signal_new (g_intern_static_string ( "notify" ), G_TYPE_FROM_CLASS ( class ), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GObjectClass, notify), NULL, NULL, g_cclosure_marshal_VOID__PARAM, G_TYPE_NONE, 1, G_TYPE_PARAM); /* Install a check function that we'll use to verify that classes that * implement an interface implement all properties for that interface */ g_type_add_interface_check (NULL, object_interface_check_properties); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | static void gst_object_class_init (GstObjectClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); #ifndef GST_DISABLE_TRACE _gst_object_trace = gst_alloc_trace_register (g_type_name (GST_TYPE_OBJECT)); #endif gobject_class->set_property = gst_object_set_property; gobject_class->get_property = gst_object_get_property; g_object_class_install_property (gobject_class, ARG_NAME, g_param_spec_string ( "name" , "Name" , "The name of the object" , NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); /** * GstObject::parent-set: * @gstobject: a #GstObject * @parent: the new parent * * Emitted when the parent of an object is set. */ gst_object_signals[PARENT_SET] = g_signal_new ( "parent-set" , G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, parent_set), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT); /** * GstObject::parent-unset: * @gstobject: a #GstObject * @parent: the old parent * * Emitted when the parent of an object is unset. */ gst_object_signals[PARENT_UNSET] = g_signal_new ( "parent-unset" , G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, parent_unset), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_OBJECT); #if !defined(GST_DISABLE_LOADSAVE) && !defined(GST_REMOVE_DEPRECATED) /** * GstObject::object-saved: * @gstobject: a #GstObject * @xml_node: the xmlNodePtr of the parent node * * Trigered whenever a new object is saved to XML. You can connect to this * signal to insert custom XML tags into the core XML. */ /* FIXME This should be the GType of xmlNodePtr instead of G_TYPE_POINTER * (if libxml would use GObject) */ gst_object_signals[OBJECT_SAVED] = g_signal_new ( "object-saved" , G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstObjectClass, object_saved), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER); klass->restore_thyself = (( void (*)(GstObject * object, gpointer self)) *gst_object_real_restore_thyself); #endif /** * GstObject::deep-notify: * @gstobject: a #GstObject * @prop_object: the object that originated the signal * @prop: the property that changed * * The deep notify signal is used to be notified of property changes. It is * typically attached to the toplevel bin to receive notifications from all * the elements contained in that bin. */ gst_object_signals[DEEP_NOTIFY] = g_signal_new ( "deep-notify" , G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS, G_STRUCT_OFFSET (GstObjectClass, deep_notify), NULL, NULL, gst_marshal_VOID__OBJECT_PARAM, G_TYPE_NONE, 2, GST_TYPE_OBJECT, G_TYPE_PARAM); klass->path_string_separator = "/" ; /* FIXME 0.11: Store this directly in the class struct */ klass->lock = g_slice_new (GStaticRecMutex); g_static_rec_mutex_init (klass->lock); klass->signal_object = g_object_newv (gst_signal_object_get_type (), 0, NULL); /* see the comments at gst_object_dispatch_properties_changed */ gobject_class->dispatch_properties_changed = GST_DEBUG_FUNCPTR (gst_object_dispatch_properties_changed); gobject_class->dispose = gst_object_dispose; gobject_class->finalize = gst_object_finalize; } |
1. g_type_class_ref(G_TYPE_OBJECT)
1 2 | g_type_init(); g_type_class_ref(G_TYPE_OBJECT); |
result:
1 2 3 4 5 6 7 8 | Entering g_type_class_ref Type:GObject +Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref |
2.
1 2 3 | g_type_init(); g_type_class_ref(G_TYPE_OBJECT); g_type_class_ref(GST_TYPE_OBJECT); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | Entering g_type_class_ref Type:GObject +Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref Entering g_type_class_ref Type:GstObject +Entering g_type_class_ref Type:GObject -Leaving g_type_class_ref +Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() ++Entering g_type_class_ref Type:GParamString +++Entering g_type_class_ref Type:GParam ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject +++Entering g_type_class_ref Type:GObject ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject --Leaving g_type_class_ref -Leaving type_class_init_Wm Leaving g_type_class_ref |
3.
1 2 | g_type_init(); g_type_class_ref(GST_TYPE_OBJECT); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Entering g_type_class_ref Type:GstObject +Entering g_type_class_ref Type:GObject ++Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() --Leaving type_class_init_Wm -Leaving g_type_class_ref +Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() ++Entering g_type_class_ref Type:GParamString +++Entering g_type_class_ref Type:GParam ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject +++Entering g_type_class_ref Type:GObject ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject --Leaving g_type_class_ref -Leaving type_class_init_Wm Leaving g_type_class_ref |
4.
1 2 3 4 | g_type_init(); g_type_class_ref(G_TYPE_OBJECT); g_type_class_ref(GST_TYPE_OBJECT); g_type_class_ref(GST_TYPE_ELEMENT); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | ============================= Entering g_type_class_ref Type:GObject +Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref ============================= Entering g_type_class_ref Type:GstObject +Entering g_type_class_ref Type:GObject -Leaving g_type_class_ref +Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() ++Entering g_type_class_ref Type:GParamString +++Entering g_type_class_ref Type:GParam ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject +++Entering g_type_class_ref Type:GObject ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject --Leaving g_type_class_ref -Leaving type_class_init_Wm Leaving g_type_class_ref ============================= Entering g_type_class_ref Type:GstElement +Entering g_type_class_ref Type:GstObject -Leaving g_type_class_ref +Entering type_class_init_Wm Call GstElement.class_init_base() Call GObject.class_init_base() Call GstElement.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref |
5.
1 2 | g_type_init(); g_type_class_ref(GST_TYPE_ELEMENT); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | Entering g_type_class_ref Type:GstElement +Entering g_type_class_ref Type:GstObject ++Entering g_type_class_ref Type:GObject +++Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() +++Entering g_type_class_ref Type:GParamString ++++Entering g_type_class_ref Type:GParam +++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() -----Leaving type_class_init_Wm ----Leaving g_type_class_ref ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering g_type_class_ref Type:GstSignalObject ++++Entering g_type_class_ref Type:GObject ----Leaving g_type_class_ref ++++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering g_type_class_ref Type:GstSignalObject ---Leaving g_type_class_ref --Leaving type_class_init_Wm -Leaving g_type_class_ref +Entering type_class_init_Wm Call GstElement.class_init_base() Call GObject.class_init_base() Call GstElement.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref |
6.
1 2 | g_type_init(); g_type_class_ref(GST_TYPE_PIPELINE); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | Entering g_type_class_ref Type:GstPipeline +Entering g_type_class_ref Type:GstBin ++Entering g_type_class_ref Type:GstElement +++Entering g_type_class_ref Type:GstObject ++++Entering g_type_class_ref Type:GObject +++++Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() -----Leaving type_class_init_Wm ----Leaving g_type_class_ref ++++Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() +++++Entering g_type_class_ref Type:GParamString ++++++Entering g_type_class_ref Type:GParam +++++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() -------Leaving type_class_init_Wm ------Leaving g_type_class_ref ++++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ------Leaving type_class_init_Wm -----Leaving g_type_class_ref +++++Entering g_type_class_ref Type:GstSignalObject ++++++Entering g_type_class_ref Type:GObject ------Leaving g_type_class_ref ++++++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ------Leaving type_class_init_Wm -----Leaving g_type_class_ref +++++Entering g_type_class_ref Type:GstSignalObject -----Leaving g_type_class_ref ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GstElement.class_init_base() Call GObject.class_init_base() Call GstElement.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering type_class_init_Wm Call GstBin.class_init_base() Call GstElement.class_init_base() Call GObject.class_init_base() Call GstBin.class_init() +++Entering g_type_class_ref Type:GParamBoolean ++++Entering g_type_class_ref Type:GParam ----Leaving g_type_class_ref ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamBoolean.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering g_type_class_ref Type:GParamBoolean ---Leaving g_type_class_ref +++Entering g_type_class_ref Type:GstBin ++++Entering g_type_class_ref Type:GstElement ----Leaving g_type_class_ref ---Leaving g_type_class_ref --Leaving type_class_init_Wm -Leaving g_type_class_ref +Entering type_class_init_Wm Call GstPipeline.class_init_base() Call GstBin.class_init_base() Call GstElement.class_init_base() Call GObject.class_init_base() Call GstPipeline.class_init() ++Entering g_type_class_ref Type:GParamUInt64 +++Entering g_type_class_ref Type:GParam ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamUInt64.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GParamBoolean --Leaving g_type_class_ref -Leaving type_class_init_Wm Leaving g_type_class_ref |
上面的base调用打印应该是反的
Call GstPipeline.class_init_base()
Call GstBin.class_init_base()
Call GstElement.class_init_base()
Call GObject.class_init_base()
实际是:
GObject.class_init_base()
GstElement.class_init_base()
GstBin.class_init_base()
GstPipeline.class_init_base()
先父亲后儿子的顺序,调用base_init():
父 | Me (当前) | 儿子 | 孙子 | 重孙子 |
GObject | GstObject | GstElement | GstBin | GstPipeline |
g_object_base_class_init() | gst_element_base_class_init | gst_bin_base_init | gst_pipeline_base_init | |
g_object_do_class_init() | gst_object_class_init() | gst_element_class_init | gst_bin_class_init | gst_pipeline_class_init |
g_object_init() | gst_object_init() | gst_element_init | gst_bin_init | gst_pipeline_init |
xxx_yyy_get_type(), 是创建type node, 并且,绑定自己定义的一些APIs;
g_type_class_ref(), 是调用用户的一些class: APIs,
先调用base_init() [老子--> 儿子-->当前],
在调用class_init()
这个时候,对象实例依然没有创建。
下面就要看g_object_newv的实力了!
examples:
1.
1 | g_object_new(G_TYPE_OBJECT, NULL); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | GEnum->is_classed = 1 GFlags->is_classed = 1 GParam->is_instantiatable = 1 GObject->is_instantiatable = 1 GParamChar->is_instantiatable = 1 GParamUChar->is_instantiatable = 1 GParamBoolean->is_instantiatable = 1 GParamInt->is_instantiatable = 1 GParamUInt->is_instantiatable = 1 GParamLong->is_instantiatable = 1 GParamULong->is_instantiatable = 1 GParamInt64->is_instantiatable = 1 GParamUInt64->is_instantiatable = 1 GParamUnichar->is_instantiatable = 1 GParamEnum->is_instantiatable = 1 GParamFlags->is_instantiatable = 1 GParamFloat->is_instantiatable = 1 GParamDouble->is_instantiatable = 1 GParamString->is_instantiatable = 1 GParamParam->is_instantiatable = 1 GParamBoxed->is_instantiatable = 1 GParamPointer->is_instantiatable = 1 GParamValueArray->is_instantiatable = 1 GParamObject->is_instantiatable = 1 GParamOverride->is_instantiatable = 1 GParamGType->is_instantiatable = 1 GParamVariant->is_instantiatable = 1 ============================= Entering g_type_class_ref Type:GObject +Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() -Leaving type_class_init_Wm Leaving g_type_class_ref Entering g_type_class_ref Type:GObject Leaving g_type_class_ref Call GObject.instance_init() |
2.
1 | g_object_new(GST_TYPE_OBJECT,NULL); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | GEnum->is_classed = 1 GFlags->is_classed = 1 GParam->is_instantiatable = 1 GObject->is_instantiatable = 1 GParamChar->is_instantiatable = 1 GParamUChar->is_instantiatable = 1 GParamBoolean->is_instantiatable = 1 GParamInt->is_instantiatable = 1 GParamUInt->is_instantiatable = 1 GParamLong->is_instantiatable = 1 GParamULong->is_instantiatable = 1 GParamInt64->is_instantiatable = 1 GParamUInt64->is_instantiatable = 1 GParamUnichar->is_instantiatable = 1 GParamEnum->is_instantiatable = 1 GParamFlags->is_instantiatable = 1 GParamFloat->is_instantiatable = 1 GParamDouble->is_instantiatable = 1 GParamString->is_instantiatable = 1 GParamParam->is_instantiatable = 1 GParamBoxed->is_instantiatable = 1 GParamPointer->is_instantiatable = 1 GParamValueArray->is_instantiatable = 1 GParamObject->is_instantiatable = 1 GParamOverride->is_instantiatable = 1 GParamGType->is_instantiatable = 1 GParamVariant->is_instantiatable = 1 ============================= GstObject->is_instantiatable = 1 Entering g_type_class_ref Type:GstObject +Entering g_type_class_ref Type:GObject ++Entering type_class_init_Wm Call GObject.class_init_base() Call GObject.class_init() --Leaving type_class_init_Wm -Leaving g_type_class_ref +Entering type_class_init_Wm Call GObject.class_init_base() Call GstObject.class_init() ++Entering g_type_class_ref Type:GParamString +++Entering g_type_class_ref Type:GParam ++++Entering type_class_init_Wm Call GParam.class_init_base() Call GParam.class_init() ----Leaving type_class_init_Wm ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GParam.class_init_base() Call GParamString.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref Call GParam.instance_init() Call GParamString.instance_init() GstSignalObject->is_instantiatable = 1 ++Entering g_type_class_ref Type:GstSignalObject +++Entering g_type_class_ref Type:GObject ---Leaving g_type_class_ref +++Entering type_class_init_Wm Call GObject.class_init_base() Call GstSignalObject.class_init() ---Leaving type_class_init_Wm --Leaving g_type_class_ref ++Entering g_type_class_ref Type:GstSignalObject --Leaving g_type_class_ref Call GObject.instance_init() Call GstSignalObject.instance_init() -Leaving type_class_init_Wm Leaving g_type_class_ref GLib-GObject-WARNING **: cannot create instance of abstract (non-instantiatable) type `GstObject' aborting... |
阶段 | 相应API | 作用 | GObject 调用顺序 | GstObject | GstElement |
1 | xxx_yyy_get_type() |
创建TypeNode, 并且赋值一些APIs: base_class_init() class_init() instance_init(), 等等 |
|||
2 | g_type_class_ref() |
调用base_class_init() 从父-->子, |
g_object_base_class_init() |
1. 父类:g_object_base_class_init() 2. 自己没有base_init() |
1. 爷爷:g_object_base_class_init() 2. 父亲没有base_init() 3. gst_element_base_class_init |
调用class_init(), 指定各种APIs 包括class->constructor(), set_property()/get_property() dispose()/finalize() |
g_object_do_class_init() |
gst_object_class_init() 1. 首选取得GObjectClass 2. 重载一些函数 3. 装载一些自己的signal |
gst_element_class_init() 1. 首选取得GObjectClass 2. 把GObjectClass的一些函数换成自己的(重载) 3. 装载自己的信号 |
||
3 | g_object_new() |
调用class->constructor() --> g_type_create_instance() --> 父类的instance(), 自己的instance() |
g_object_constructor()->g_type_create_instance() -> 1. g_object_init() |
g_object_constructor()->g_type_create_instance() -> 1. 父亲:g_object_init() 2.自己:gst_object_init() |
g_object_constructor()->g_type_create_instance() -> 1. 爷爷:g_object_init() 2.父亲:gst_object_init() 3. 自己:gst_element_init()
|
set properties |
疑问:在同一进程内,如果同时注册N个话,如果管理?
“用时”注册,会浪费时间吗?
2024年2月21日 21:17
Awesome article, it was exceptionally helpful! I simply began in this and I'm becoming more acquainted with it better. The post is written in very a good manner and it contains many useful information for me. Thank you very much and will look for more postings from you.