GLib/Gstreamer代码浅析

本文详细介绍了GLib库的使用,包括安装、模块、优势及特性,如GModule、GMainLoop、线程、GObject等。此外,探讨了GStreamer的重要概念,如Pipeline、Element、Bin、Pad&GhostPad、Caps以及插件、多线程、通信机制等。通过实例分析了openh264插件的编译和使用,以及音视频同步策略。最后,对GStreamer的基础框架进行了代码层面的分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GLib

概述

  • 实现跨平台

  • 避免重复造轮子

GLib的上下层结构:

GLib的组成部分:

GLib代码组成:

GModule代码组成:

GObject代码组成:

GIO代码组成:530个文件,太多不列了!

如何使用glib

安装glib(ubuntu系统)

直接通过命令安装:


sudo apt install -y libglib2.0-dev

下载源码包自己编译安装:


git clone https://gitlab.gnome.org/GNOME/glib.git
cd glib
mkdir out
meson out
cd out
ninja
sudo ninja install
使用glib

包含相关的头文件,即可开展编程


#include <glib.h>                       //GLib#include <gmodule.h>                    //GModlule#include <glib-object.h>                //GObject#include <gio/gdesktopappinfo.h>        //GIO
#include <gio/gfiledescriptorbased.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <gio/gunixfdmessage.h>
#include <gio/gunixinputstream.h>
#include <gio/gunixmounts.h>
#include <gio/gunixoutputstream.h>
编译

--------------------------------------简易版--------------------------------------------------
gcc glib_test.c -o glib_test `pkg-config --libs --cflags glib-2.0`

fuqiang@fuqiang-virtual:~/workspace$ pkg-config --libs --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0--------------------------------------完整版--------------------------------------------------
gcc glib_test.c -o glib_test `pkg-config --libs --cflags glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0`

fuqiang@fuqiang-virtual:~/workspace/test_gstreamer$ pkg-config --libs --cflags glib-2.0 gmodule-2.0 gobject-2.0 gio-2.0
-pthread -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -Wl,--export-dynamic -lgmodule-2.0 -pthread -lgio-2.0 -lgobject-2.0 -lglib-2.0

优势

  • 跨平台的动态库加载函数(GModule)

  • 事件循环分发处理机制GMainLoop (GLib)

  • 跨平台的线程(线程池)函数,信号量函数,互斥锁函数(GLib)

  • 提供了异步队列、线性表、动态数组、单/双向链表、哈希表、多叉树、平衡二叉树、字符串等常用容器(GLib)

  • 词法分析,xml语言解析、ini文件读写等功能(GLib)

  • 命令行参数解析(GLib)

  • 一套完整的log机制(GLib)

  • slice内存分配结构(GLib)

  • 简单的正则表达式功能(GLib)

  • GObject面向对象封装设计(GObject)

  • IO函数(GIO)

特性说明(docs.gtk.org/glib/index.html)

GModule(Dynamically loaded modules)

Gstreamer中的动态加载插件就是通过这个实现


#if     (G_MODULE_IMPL == G_MODULE_IMPL_DL)
#include "gmodule-dl.c"
#elif   (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
#include "gmodule-win32.c"
#elif   (G_MODULE_IMPL == G_MODULE_IMPL_AR)
#include "gmodule-ar.c"

GModule结构体定义:


struct _GModule
{
  gchar *file_name;
  gpointer handle;
  guint ref_count : 31;         //引用计数,多次open
  guint is_resident : 1;        //需要常驻,不能unload
  GModuleUnload unload;         //回调函数
  GModule *next;                //加载的modules链表
};

一些代码:


GModule*
g_module_open_full (const gchar   *file_name,
                    GModuleFlags   flags,
                    GError       **error)
{
...
  module = g_module_find_by_name (file_name);
  if (module)
  {
    module->ref_count++;

  }
...
  /* we don't call unload() if the initialization check failed. */
  if (!check_failed)
    g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
...
}


gboolean
g_module_close (GModule *module)
{
...
  module->ref_count--;
  if (!module->ref_count && !module->is_resident && module->unload)
  {
    GModuleUnload unload;

    unload = module->unload;
    module->unload = NULL;
    unload (module);
  }
...
}

官方示例:


// the function signature for 'say_hello'
typedef void (* SayHelloFunc) (const char *message);

gboolean
just_say_hello (const char *filename, GError **error)
{
  SayHelloFunc say_hello;
  GModule *module;

  module = g_module_open (filename, G_MODULE_BIND_LAZY);//dlopen
  if (module == NULL)
    {
      g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH,
                   "%s", g_module_error ());
      return FALSE;
    }

  if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello))        //dlsym    {
      g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
                   "%s: %s", filename, g_module_error ());

      if (!g_module_close (module))
        g_warning ("%s: %s", filename, g_module_error ());

      return FALSE;
    }

  if (say_hello == NULL)
    {
      g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN,
                   "symbol say_hello is NULL");

      if (!g_module_close (module))
        g_warning ("%s: %s", filename, g_module_error ());

      return FALSE;
    }

  // call our function in the module
  say_hello ("Hello world!");

  if (!g_module_close (module))        //dlclose
    g_warning ("%s: %s", filename, g_module_error ());

  return TRUE;
 }
GMainLoop(gmain.h/gmain.c)
  • 基于IO多路复用(select/poll/epoll)

  • 事件动态添加

  • 优先级管理


#define G_PRIORITY_HIGH            -100
#define G_PRIORITY_DEFAULT          0
#define G_PRIORITY_HIGH_IDLE        100
#define G_PRIORITY_DEFAULT_IDLE     200
#define G_PRIORITY_LOW              300        //background

结构体:


struct _GMainLoop
{
  GMainContext *context;
  gboolean is_running; /* (atomic) */
  gint ref_count;  /* (atomic) */
};
...
struct _GSource
{
  /*< private >*/
  gpointer callback_data;
  GSourceCallbackFuncs *callback_funcs;

  const GSourceFuncs *source_funcs;
  guint ref_count;

  GMainContext *context;gint priority;//优先级管理
  guint flags;
  guint source_id;

  GSList *poll_fds;

  GSource *prev;        //检索,添加,删除
  GSource *next;

  char    *name;

  GSourcePrivate *priv;
};

常规事件处理


#include<glib.h> 
GMainLoop* loop;

gint counter = 10;
gboolean callback(gpointer arg)
{
    if(--counter == 0){
        g_main_loop_quit(loop);
        return FALSE;
    }
    return TRUE;
}
 
int main(int argc, char* argv[])
{
    if(g_thread_supported() == 0)
        g_thread_init(NULL);
    loop = g_main_loop_new(NULL, FALSE);
    g_timeout_add(100, callback, NULL);  //增加一个定时器,100毫秒运行一次callback
    g_main_loop_run(loop);
    g_main_loop_unref(loop);
    return 0;
}

unref:


g_main_loop_unref (GMainLoop *loop)
{
  g_return_if_fail (loop != NULL);
  g_return_if_fail (g_atomic_int_get (&loop->ref_count) > 0);

  if (!g_atomic_int_dec_and_test (&loop->ref_count))
    return;

  g_main_context_unref (loop->context);
  g_free (loop);
}

自定义事件处理


#include <glib.h>
#include <stdio.h>
#include <strings.h>
GMainLoop* loop;
//当stdin有数据可读时被GSource调用的回调函数
gboolean callback(GIOChannel *channel)
{
    gchar* str;
    gsize len;
    //从stdin读取一行字符串
    g_io_channel_read_line(channel, &str, &len, NULL, NULL);
    //去掉回车键()
    while(len > 0 && (str[len-1] == '/r' || str[len-1] == '/n'))
        str[--len]='/0';
    //反转字符串
    for(;len;len--)
        g_print("%c",str[len-1]);
    g_print("/n");
    //判断结束符
    if(strcasecmp(str, "q") == 0){
        g_main_loop_quit(loop);
    }
    g_free(str);
}
void add_source(GMainContext *context)
{
    GIOChannel* channel;
    GSource* source;
    //这里我们监视stdin是否可读, stdin的fd默认等于1
    channel = g_io_channel_unix_new(1);
    //g_io_create_watch创建一个默认的io监视作用的GSource,参数G_IO_IN表示监视stdin的读取状态
    source = g_io_create_watch(channel, G_IO_IN);
    g_io_channel_unref(channel);
    //设置stdin可读的时候调用的回调函数
    g_source_set_callback(source, (GSourceFunc)callback, channel, NULL);
    //把GSource附加到GMainContext
    g_source_attach(source, context);
    g_source_unref(source);
}
int main(int argc, char* argv[])
{
    GMainContext *context;
    if(g_thread_supported() == 0)
        g_thread_init(NULL);
    context = g_main_context_new();
    add_source(context);
    //把Context赋给GMainLoop
    loop = g_main_loop_new(context, FALSE);
    g_print("input string('q' to quit)/n");
    g_main_loop_run(loop);
    g_main_loop_unref(loop);
    g_main_context_unref(context);
    return 0;
}
Thread(gthread.h/gthread.c)

typedef struct _GThread         GThread;

typedef struct _GMutex          GMutex;
typedef struct _GRecMutex       GRecMutex;
typedef struct _GRWLock         GRWLock;
typedef struct _GCond           GCond;

官方示例:


#include <glib.h>

void thread_call(gpointer data)
{
    gint i = GPOINTER_TO_INT(data);
    g_print("%d\n", i);
    g_print("Thread %d was created\n", i);
}

int main()
{
    gint i;
    GThread* thread = NULL;
    GError*   error = NULL;

if (!g_thread_supported())
{
    g_thread_init(NULL);
}

for (i = 1; i < 10; i++)
{
    thread = g_thread_create((GThreadFunc)thread_call,(gpointer)i, FALSE, &error);
    g_usleep(500);
    if (thread == NULL)
    {
        g_critical("Create thread error: %s\n",error->message);
        g_error_free(error);
    }
}

return 0;
}
ThreadPool(gthreadpool.h/gthreadpool.c)

频繁创建和销毁执行过程相似而数据不同的线程,系统的效率和资源的利用率将会受到很大的影响--->threadpool


#include <glib.h>
#include <glib/gprintf.h>
#include <unistd.h>
#include <sys/syscall.h>

//线程执行函数,进入后打印数据,并睡眠5秒
void thread_execute (gpointer data, gpointer user_data)
{
	g_printf("thread_execute %ld in\n", syscall(__NR_gettid));
	g_printf("thread_execute %ld data is : %d\n", syscall(__NR_gettid), *((gint *)data));
	g_usleep (5000000);
	g_printf("thread_execute %ld out\n", syscall(__NR_gettid));
}
 
gint data[10];
int main(int argc, char **argv)
{
	g_printf ("main in\n");
 
	gint count;
	GError *gerr = NULL;
	GThreadPool *gpool = NULL;
	//最大同时执行2个线程,由于exclusive设置为FALSE,所以不会有错误发生,error被设置为NULL
	gpool = g_thread_pool_new (thread_execute, NULL, 2, FALSE, NULL);

	//线程池中最大允许线程数3个
	if(!g_thread_pool_set_max_threads (gpool, 3, &gerr))
		g_printf("g_thread_pool_set_max_threads is error: %s\n", gerr->message);
 	
	/** 
	* 实际线程池中最多有3个线程同时运行 
	*/  
	for (count = 0; count < (sizeof(data)/sizeof(gint)); count++)
	{
		data[count] = count;
		g_thread_pool_push(gpool, (gpointer)(&(data[count])), &gerr);
		if(gerr != NULL)
		{
			g_printf("g_thread_pool_push is error: %s\n", gerr->message);
		}
	}
 
	g_usleep (100000);
	
	//插入优先级高的新任务
	if(g_thread_pool_move_to_front (gpool, (gpointer)(&(data[9]))))
		g_printf("g_thread_pool_move_to_front is 9\n");
	
	//立即释放,不继续执行任务队列
	//g_thread_pool_free (gpool, TRUE, TRUE);
	//等待任务队列中的任务全部执行完成
	g_thread_pool_free (gpool, FALSE, TRUE);

	g_printf ("main out\n");
        return 0;
}
AsyncQueue(gasyncqueue.h/gasyncqueue.c)

#include <glib.h>

static gpointer test_aqueue_push_func(gpointer data)
{
    GAsyncQueue *aqueue = NULL;

    g_print("%s \n", __FUNCTION__);
    g_print("delay 2 seconds to push data \n");
    g_usleep(2*1000*1000);

    aqueue = (GAsyncQueue *)data;
    g_async_queue_push(aqueue, GINT_TO_POINTER(99));

    return NULL;
}

static gpointer test_aqueue_pop_func(gpointer data)
{
    gpointer val = NULL;
    GAsyncQueue *aqueue = NULL;
    g_print("%s \n", __FUNCTION__);

    aqueue = (GAsyncQueue *)data;
    val = g_async_queue_pop(aqueue);
    g_print("val: %d \n", GPOINTER_TO_INT(val));

    return NULL;
}

gint main(gint argc, gchar **argv)
{
    GThread *thd_push, *thd_pop;
    GAsyncQueue *aqueue = NULL;

    aqueue = g_async_queue_new();

    thd_push = g_thread_new("thd_push", test_aqueue_push_func, aqueue);
    thd_pop  = g_thread_new("thd_pop", test_aqueue_pop_func, aqueue);

    g_thread_join(thd_push);
    g_thread_join(thd_pop);

    g_async_queue_unref(aqueue);

    return 0;
}
线性表
  • 顺序表GArray(garray.h/garray.c)

  • 单链表GSList(gslist.h/gslist.c)

  • 双链表GList(glist.h/glist.c)

词法分析
  • XML语言解析GMarkupParser(gmarkup.h/gmarkup.c)

  • ini文件解析GKeyFile(gkeyfile.h/gkeyfile.c)

命令行参数解析GOption(goption.h/goption.c)

#include <glib.h>
#include <locale.h>
 
static  gint repeats = 2;
static  gint max_size = 8;
static  gboolean verbose = FALSE;
static  gboolean beep = FALSE;
 
static  GOptionEntry entries[] =
{
//   longname shortname flag     arg           arg_data     description             arg_description
    {"repeats" ,   'r' , 0, G_OPTION_ARG_INT,  &repeats,  "Average over N repetitions" ,  "N" },
    {"max-size" ,  'm' , 0, G_OPTION_ARG_INT,  &max_size, "Test up to 2^M items" ,        "M" },
    {"verbose" ,   'v' , 0, G_OPTION_ARG_NONE, &verbose,  "Be verbose" ,                   NULL},
    {"beep" ,      'b' , 0, G_OPTION_ARG_NONE, &beep,     "Beep when done" ,               NULL},
    {NULL}
};
 
 
int main (int  argc,  char  *argv[])
{
    GError *error = NULL;
    GOptionContext *context = NULL;
    GOptionGroup *group = NULL;
 
    // 创建一个新的选项上下文
    context = g_option_context_new("- test tree model performance" );
    g_option_context_add_main_entries(context, entries, NULL);
 
    //添加要在选项列表之前的--help输出中显示的字符串。 这通常是程序功能的摘要
    g_option_context_set_summary(context, "This is a glib demo" );
 
    // 解析命令行参数,识别已添加到上下文的选项
    if  (!g_option_context_parse(context, &argc, &argv, &error))
    {
        exit (1);
    }
 
    // 释放被解析的参数
    g_option_context_free(context);
 
    g_print("Now value is: repeats=%d, max_size=%d, verbose=%d, beep=%d\n",
            repeats, max_size, verbose, beep);
 
    return  0;
}

执行情况:


fuqiang@fuqiang-virtual:~/workspace/test_gstreamer$ ./glib_test_option -h
Usage:
  glib_test_option [OPTION?] - test tree model performance

This is a glib demo

Help Options:
  -h, --help           Show help options

Application Options:
  -r, --repeats=N      Average over N repetitions
  -m, --max-size=M     Test up to 2^M items
  -v, --verbose        Be verbose
  -b, --beep           Beep when done

fuqiang@fuqiang-virtual:~/workspace/test_gstreamer$ ./glib_test_option
Now value is: repeats=2, max_size=8, verbose=0, beep=0
fuqiang@fuqiang-virtual:~/workspace/test_gstreamer$ ./glib_test_option -r 1000
Now value is: repeats=1000, max_size=8, verbose=0, beep=0
Log机制(gmessages.h/gmessages.c)

跨平台,统一linux和win32:


#ifdef G_OS_UNIX
#include <unistd.h>
#endif

#ifdef G_OS_WIN32
#include <process.h>            /* For getpid() */
#include <io.h>
#include <windows.h>
#endif

log等级划分:


#define g_error(...)  G_STMT_START {                                            \
                        g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__); \
                        for (;;) ;                                              \
                      } G_STMT_END
#define g_message(...)  g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__)
#define g_critical(...) g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__)
#define g_warning(...)  g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__)
#define g_info(...)     g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__)
#define g_debug(...)    g_log_structured_standard (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
                                                   __FILE__, G_STRINGIFY (__LINE__), \
                                                   G_STRFUNC, __VA_ARGS__)

使用:


g_error ("%s: failed to allocate memory", G_STRLOC);
内存分配
  • gmem.h/gmem.c

  • gslice.h/gslice.c

  • 推荐使用gslice

gslice:

  • 分层设计

  • 用于优化许多大小相等的块的分配,线程内存空闲列表,快速满足已知结构的内存分配

  • 对齐约束而未使用的内存用于缓存着色(块地址的随机分布),以提高CPU缓存利用率


gchar *mem[10000];
gint i;

// Allocate 10000 blocks.
for (i = 0; i < 10000; i++)
{
    mem[i] = g_slice_alloc (50);

    // Fill in the memory with some junk.
    for (j = 0; j < 50; j++)
      mem[i][j] = i * j;
}

// Now free all of the blocks.
for (i = 0; i < 10000; i++)
    g_slice_free1 (50, mem[i]);
正则表达式GRegex(gregex.h/gregex.c)

#include <glib.h>

int main (int argc, char** argv)
{
    GRegex* regex;
    GMatchInfo *match_info;
    GError *error = NULL;
    const gchar *str = "11aa222bb33333cccc44444dddddddd";
    const gchar *pat = "[0-9]+";    regex = g_regex_new(pat, 0, 0, &error);
    g_regex_match(regex, str, 0, &match_info);

    while (g_match_info_matches(match_info)) {
        gchar* word = g_match_info_fetch(match_info, 0);
        g_print("%s \n",word);
        g_free(word);

        g_match_info_next(match_info, NULL);
    }

    g_match_info_free(match_info);
    g_regex_unref(regex);

  return 0;
}
GObject(面向对象实现)

封装&继承:

G_DEFINE_TYPE:


G_DEFINE_TYPE
	G_DEFINE_TYPE_EXTENDED
		_G_DEFINE_TYPE_EXTENDED_BEGIN
			_G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
			_G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
		_G_DEFINE_TYPE_EXTENDED_END


// G_DEFINE_TYPE
#define G_DEFINE_TYPE(TN, t_n, T_P)			    G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {})
#define G_DEFINE_TYPE_EXTENDED(TN, t_n, T_P, _f_, _C_)	 _G_DEFINE_TYPE_EXTENDED_BEGIN (TN, t_n, T_P, _f_) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
//_G_DEFINE_TYPE_EXTENDED_BEGIN
#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \
  _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \
  _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \

//_G_DEFINE_TYPE_EXTENDED_END
#define _G_DEFINE_TYPE_EXTENDED_END()	\
        /* following custom code */	\
      }					\
      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); \
    }					\
  return g_define_type_id__volatile;	\
} /* closes type_name##_get_type() */

// _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \
\
static void     type_name##_init              (TypeName        *self); \
static void     type_name##_class_init        (TypeName##Class *klass); \
static gpointer type_name##_parent_class = NULL; \
static gint     TypeName##_private_offset; \
\
_G_DEFINE_TYPE_EXTENDED_CLASS_INIT(TypeName, type_name) \
\
G_GNUC_UNUSED \
static inline gpointer \
type_name##_get_instance_private (TypeName *self) \
{ \
  return (G_STRUCT_MEMBER_P (self, TypeName##_private_offset)); \
} \
\
GType \
type_name##_get_type (void) \
{ \
  static volatile gsize g_define_type_id__volatile = 0;
  /* Prelude goes here */

// _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER
#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \
  if (g_once_init_enter (&g_define_type_id__volatile))  \
    { \
      GType g_define_type_id = \
        g_type_register_static_simple (TYPE_PARENT, \
                                       g_intern_static_string (#TypeName), \
                                       sizeof (TypeName##Class), \
                                       (GClassInitFunc)(void (*)(void)) type_name##_class_intern_init, \
                                       sizeof (TypeName), \
                                       (GInstanceInitFunc)(void (*)(void)) type_name##_init, \
                                       (GTypeFlags) flags); \
      { /* custom code follows */

将下面代入:

  • TypeName:MyObject

  • type_name:my_object

  • TYPE_PARENT:G_TYPE_OBJECT


static void     my_object_init              (MyObject        *self);
static void     my_object_class_init        (MyObjectClass *klass);

static gpointer my_object_parent_class = NULL;
static gint     MyObject_private_offset;

static void     my_object_class_intern_init (gpointer klass)
{
  my_object_parent_class = g_type_class_peek_parent (klass);//获取父类
  if (MyObject_private_offset != 0)
    g_type_class_adjust_private_offset (klass, &MyObject_private_offset);
  my_object_class_init ((MyObjectClass*) klass);//子类初始化
}

G_GNUC_UNUSED
static inline gpointer
my_object_get_instance_private (TypeName *self)
{
  return (G_STRUCT_MEMBER_P (self, MyObject_private_offset));
}

GType
my_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 ("MyObject"),
                                       sizeof (MyObjectClass),
                                       (GClassInitFunc)(void (*)(void)) my_object_class_intern_init,
                                       sizeof (TypeName),
                                       (GInstanceInitFunc)(void (*)(void)) my_object_init,
                                       (GTypeFlags) flags);

    g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
  }
  return g_define_type_id__volatile;
}

TypeNode:


/* --- structures --- */
struct _TypeNode
{
  guint        ref_count;  /* (atomic) */

  GTypePlugin *plugin;
  guint        n_children; /* writable with lock */
  guint        n_supers : 8;
  guint        n_prerequisites : 9;
  guint        is_classed : 1;
  guint        is_instantiatable : 1;
  guint        mutatable_check_cache : 1;	/* combines some common path checks */
  GType       *children; /* writable with lock */
  TypeData    *data;
  GQuark       qname;
  GData       *global_gdata;
  union {
    GAtomicArray iface_entries;		/* for !iface types */
    GAtomicArray offsets;
  } _prot;
  GType       *prerequisites;
  GType        supers[1]; /* flexible array */
};

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

  g_return_val_if_fail (node != NULL, NULL);

  /* 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->is_classed && node->data && NODE_PARENT_TYPE (node))
    {
      node = lookup_type_node_I (NODE_PARENT_TYPE (node)); //#define NODE_PARENT_TYPE(node) (node->supers[1])
      class = node->data->class.class;
    }
  else if (NODE_PARENT_TYPE (node))
    g_warning (G_STRLOC ": invalid class pointer '%p'", g_class);
  
  return class;
}

register:


GType
g_type_register_static (GType            parent_type,
			const gchar     *type_name,
			const GTypeInfo *info,
			GTypeFlags	 flags)
{
  TypeNode *pnode, *node;
  GType type = 0;
  
  g_assert_type_system_initialized ();
  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;
}


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;
  }
  else
    type = (GType) node;
  
  g_assert ((type & TYPE_ID_MASK) == 0);
  
  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));
  }
  else
  {
    node->supers[0] = type;memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));
      
    node->is_classed = pnode->is_classed;
    node->is_instantiatable = pnode->is_instantiatable;
      
    if (NODE_IS_IFACE (node))
    {
      IFACE_NODE_N_PREREQUISITES (node) = 0;
      IFACE_NODE_PREREQUISITES (node) = NULL;
    }
    else
    {
      guint j;
      IFaceEntries *entries;

      entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),
					  IFACE_ENTRIES_HEADER_SIZE,
					  0);
      if (entries)
      {
        for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)
        {
          entries->entry[j].vtable = NULL;
          entries->entry[j].init_state = UNINITIALIZED;
        }
        _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),
				      entries);
      }
    }

    i = pnode->n_children++;
    pnode->children = g_renew (GType, pnode->children, pnode->n_children);
    pnode->children[i] = type;
    }

  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,
		       (gpointer) g_quark_to_string (node->qname),
		       (gpointer) type);

  g_atomic_int_inc ((gint *)&type_registration_serial);

  return node;
}

目前为止,MyObject作为GObject的子类,已经完成了注册。

下面,看看当new一个instance的时候,进行那些操作


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

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码论斤卖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值