gobject/gstobject的初始化(包括类型,类,实例等的初始化)。

os posted @ 2013年8月28日 10:47 in GObject , 3082 阅读

gobjec相关学习文章的list.

 

Type,Class, instance 初始化,包括其中函数调用的过程总结:

阶段 相应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      

 

下面是具体的分析:

g_object_type_init()

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);


好戏都在g_type_class_ref

这个函数是个循环嵌套函数!

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对象还没有建立!

 

g_object_base_class_init

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;
}

g_object_do_class_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
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);
}

gst_object_class_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
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;
}

 

Testing:

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个话,如果管理?

“用时”注册,会浪费时间吗?

 

 

Avatar_small
seo service london 说:
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.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter