G_DEFINE_TYPE定义一个静态类型

/**
* G_DEFINE_TYPE(`G_DEFINE_TYPE_WITH_CODE`比`G_DEFINE_TYPE`就是多了一个自定义代码参数_C_):
* @TN: 新类型的名字,单词首字母大写,例如:GtkGadget。
* @t_n: 新类型的名字,单词全部小写并且用'_'符号分隔,例如gtk_gadget:
* separated by '_'.
* @T_P: 父类型的#GType,例如:GTK_TYPE_WIDGET
*/
#define G_DEFINE_TYPE(TN, t_n, T_P) G_DEFINE_TYPE_EXTENDED (TN, t_n, T_P, 0, {}) /**
* @TN: 新类型的名字,单词首字母大写,例如:GtkGadget。
* @t_n: 新类型的名字,单词全部小写并且用'_'符号分隔,例如gtk_gadget:
* separated by '_'.
* @T_P: 父类型的#GType,例如:GTK_TYPE_WIDGET
* @_f_: 传递给g_type_register_static()函数的参数#GTypeFlags
* @_C_: 插入*_get_type()函数的自定义代码
*
*/
#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展开后的代码

  • _G_DEFINE_TYPE_EXTENDED_BEGIN

实现type_name##_get_type函数的前半部

#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \
\
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; \
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) type_name##_class_intern_init, \
sizeof (TypeName), \
(GInstanceInitFunc) type_name##_init, \
(GTypeFlags) flags); \
{ /* custom code follows */
  • _C_

将自定义代码插入type_name##_get_type函数的中部,自定义代码将被/* custom code follows *//* following custom code */ 处的{}所包裹

  • _G_DEFINE_TYPE_EXTENDED_END

实现type_name##_get_type函数的后半部

#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() */

样例

* |[<!-- language="C" -->
* G_DEFINE_TYPE_EXTENDED (GtkGadget,
* gtk_gadget,
* GTK_TYPE_WIDGET,
* 0,
* G_IMPLEMENT_INTERFACE (TYPE_GIZMO,
* gtk_gadget_gizmo_init));
* ]|
* expands to
* |[<!-- language="C" -->
* static void gtk_gadget_init (GtkGadget *self);
* static void gtk_gadget_class_init (GtkGadgetClass *klass);
* static gpointer gtk_gadget_parent_class = NULL;
* static void gtk_gadget_class_intern_init (gpointer klass)
* {
* gtk_gadget_parent_class = g_type_class_peek_parent (klass);
* gtk_gadget_class_init ((GtkGadgetClass*) klass);
* }
*
* GType
* gtk_gadget_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 (GTK_TYPE_WIDGET,
* g_intern_static_string ("GtkGadget"),
* sizeof (GtkGadgetClass),
* (GClassInitFunc) gtk_gadget_class_intern_init,
* sizeof (GtkGadget),
* (GInstanceInitFunc) gtk_gadget_init,
* 0);
* {
* const GInterfaceInfo g_implement_interface_info = {
* (GInterfaceInitFunc) gtk_gadget_gizmo_init
* };
* g_type_add_interface_static (g_define_type_id, TYPE_GIZMO, &g_implement_interface_info);
* }
* g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
* }
* return g_define_type_id__volatile;
* }
* ]|
* 必须要手动实现的就是实例和类结构的定义,以及实例和类初始化函数的定义
*
* Since: 2.4
*/

Glib之GObject宏介绍的更多相关文章

  1. 017.Zabbix宏介绍

    一 宏介绍 Zabbix宏的作用是便于在模板.Items.Trigger中的引用,名称为{$名称},宏的字符范围为:A~Z/0~9/_. 如:net.tcp.service[ssh,{$SSH_POR ...

  2. Glib之GObject简介(翻译)

    GObject GObject库是Glib库的动态类型系统实现,它实现了: 基于引用计数的内存管理 实例的构造和析构 通用的set/get的属性获取方法 简单易用的信号机制 对象实例化 所述g_obj ...

  3. GObject调用父类函数

    最近在分析Gstreamer的代码时,发现GstPipeline中有如下代码: result = GST_ELEMENT_CLASS (parent_class)->change_state ( ...

  4. glib实践篇:父类与子类

    前言: 众所周知,C语言是一门面向过程的语言,但是不代表就得跟面向对象完全绝缘,在C语言库glib中有gobject那么一套面向对象的机制,基于C语言的面向对象设计便是基于该实现机制. 今天所要实践的 ...

  5. 迅为iTOP-4418/6818开发板-驱动-IO初始化配置介绍和例程

    对于所有的处理器,pad 一般可以分为两大类:IO(输入输出).Power(VDD 和GDD).类似摄像头 IO.以太网 IO.PWM 的 IO 等等,都可以统称为 IO.一个 IO,有可能能够被配置 ...

  6. zabbix宏(macro)使用:自定义监控阈值

    一.简单应用场景 zabbix在监控cpu load时并没有考虑客户端cpu的个数和核心数量,当平均5分钟的负载达到5时zabbix执行报警动作,这样是非常不合理的,笔者的被监控机器有四核和单核,现在 ...

  7. 嵌入式C语言自我修养 04:Linux 内核第一宏:container_of

    4.1 typeof 关键字 ANSI C 定义了 sizeof 关键字,用来获取一个变量或数据类型在内存中所占的存储字节数.GNU C 扩展了一个关键字 typeof,用来获取一个变量或表达式的类型 ...

  8. C语言基础知识:几种特殊的函数宏封装方式

    函数宏介绍 函数宏,即包含多条语句的宏定义,其通常为某一被频繁调用的功能的语句封装,且不想通过函数方式封装来降低额外的弹栈压栈开销. 函数宏本质上为宏,可以直接进行定义,例如: #define INT ...

  9. VIM辅导:视频教程,文档资料,经典插件

    VIM辅导:25个vim视频' 教程 '资源   转自: http://blog.jobbole.com/10250/ 编注:@程序员的那些事 12月14日在新浪微博发起的<你最常用哪些文本编辑 ...

随机推荐

  1. Oracle日常性能问题查看

    1 判断回滚段竞争的sql --当Ratio大于2时存在回滚段竞争,需要增加更多的回滚段) ratio from v$rollstat rs, v$rollname rn where rs.USN = ...

  2. zabbix的sendEmail配置

    zabbix的sendEmail配置 [root@hongquan scripts]# yum install sendmail[root@hongquan soft]# tar xvzf sendE ...

  3. 分数CSD编码

    有符号数系统:有三重值(1, 0, -1) SD编码:12 = 16 - 4 = 10000_0000 - 100 = 1_0000_0(-1)00; = 16 - 9 + 5 = 1_0000_00 ...

  4. python ftp 上传

    #!/usr/bin/python # -*-coding:utf- -*- from ftplib import FTP def ftpconnect(host,username,password) ...

  5. Python函数的进阶

    一  函数的动态参数 *agrs  位置参数动态传参 *args  接收多个位置参数 def func(*args): print(args) func("女儿国","西 ...

  6. Linux字符设备驱动实现

    Linux字符设备驱动实现 要求 编写一个字符设备驱动,并利用对字符设备的同步操作,设计实现一个聊天程序.可以有一个读,一个写进程共享该字符设备,进行聊天:也可以由多个读和多个写进程共享该字符设备,进 ...

  7. git配置和使用

    1.注册bitbucket用户登录bitbucket站点https://bitbucket.org/注册一个用户,注册后用户名为linjiqin,邮箱为linjiqin@dkhs.com. 2.Cre ...

  8. AOP操作术语

  9. Python_13-Office文件数据操作

    目录: 1.1      安装win32com模块 1.2      Access数据库操作 1.2.1       建立db1.db数据库,设计一张表t_student_b 1.3      Exc ...

  10. [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)

    解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ...