GObject-Glib Type, Object, Parameter and Signal

gobjec相关学习文章的list.

https://developer.gnome.org/gobject/stable/index.html

GObject的动态类型系统允许程序在运行时进行类型注册,它的最主要目的有两个:
1)使用面向对象的设计方法来编程。使用纯C语言设计出来的一整套面向对象的编程环境。
2)多语言交互。使Perl或者Python等解释型的脚本语言能使用GLIB提供的函数。这一目的是最主要的,所以,在学习GObject的设计时,需要牢记这一首要目标,这对理解GObject的一些奇怪的设计及特性是有较大帮助的。

Type

GValueType

(基本类型,以及操作API)

这里注册 基础类型:

1.gchar
2.guchar
3.gboolean
4.gint
5.guint
6.glong
7.gulong
8.gint64
9.guint64
10.gfloat
11.gdouble
12.gchararray
13.gpointer
14.gvariant

 

const GTypeFundamentalInfo finfo = { G_TYPE_FLAG_DERIVABLE, };

这些基础类型,是可以派生的;不可类化;不可实例化;不可深度派生

这些基础类型,可以放到下面的容器中:GValue中

并且对每种基本类型提供如下API集合:

struct _GTypeValueTable
{
  void     (*value_init)         (GValue       *value);
  void     (*value_free)         (GValue       *value);
  void     (*value_copy)         (const GValue *src_value,
				  GValue       *dest_value);
  /* varargs functionality (optional) */
  gpointer (*value_peek_pointer) (const GValue *value);
  gchar	    *collect_format;
  gchar*   (*collect_value)      (GValue       *value,
				  guint         n_collect_values,
				  GTypeCValue  *collect_values,
				  guint		collect_flags);
  gchar	    *lcopy_format;
  gchar*   (*lcopy_value)        (const GValue *value,
				  guint         n_collect_values,
				  GTypeCValue  *collect_values,
				  guint		collect_flags);
};

 

GValue  (泛型)

(基本类型的容器)

Generic values — A polymorphic(多态的) type that can hold values of any other type

在C语言里,通用类型我们一般是用void *以表示任何类型的数据。但GObject的设计初衷是为了解决多语言交互问题,所以必须设计出一套能容纳任何数据类型的通用数据类型。以便在不同的编程语言之间进行数据转换操作。这个数据类型就是GValue。

/**
 * GValue:
 * 
 * An opaque structure used to hold different types of values.
 * The data within the structure has protected scope: it is accessible only
 * to functions within a #GTypeValueTable structure, or implementations of
 * the g_value_*() API. That is, code portions which implement new fundamental
 * types.
 * #GValue users can not make any assumptions about how data is stored
 * within the 2 element @data union, and the @g_type member should
 * only be accessed through the G_VALUE_TYPE() macro.
 */
struct _GValue
{
  /*< private >*/
  GType		g_type;

  /* public for GTypeValueTable methods */
  union {
    gint	v_int;
    guint	v_uint;
    glong	v_long;
    gulong	v_ulong;
    gint64      v_int64;
    guint64     v_uint64;
    gfloat	v_float;
    gdouble	v_double;
    gpointer	v_pointer;
  } data[2];
};

还可以容纳用户自定义的类型;

GValueArray

(Value的容器)

上面的通用类型,还可以放到一个数组中进行有效的管理:GValueArray

它最主要的目的:是为了object property

Glib2.32以后,用GArray代替GValueArray了

GValueTransform

(Value的工具函数)

这个比较简单:不同类型之间的转换

GValueCollector

(Value的工具函数)

这个是把可变参数vararg à 一般的Value(gint, glong, gdouble, gpointer)

Gobject中,g_object_new()等函数可以使用可变参数,这个类型的API来提供这种转换功能。

 

 

GBoxed

对任意C结构的一个通用封装机制

这个box是不透明的,用户只要copy/free它即可。

很多类型,都被定义成了box类型:G_TYPE_BOX作为父类型

Boxed Type机制是用来包装(wrap)C语言结构体的一种机制。这里所谓的包装,其实就是在GType类型系统中注册该类型,并且该类型将成为GBoxed的子类。之后,这一类型就能够使用和GBoxed类型有关的所有函数了,如g_value_get_boxed等等。

 

下面这些类型会被注册为GBoxed的子类:

					
#define             G_TYPE_HASH_TABLE
#define             G_TYPE_DATE
#define             G_TYPE_GSTRING
#define             G_TYPE_STRV
#define             G_TYPE_REGEX
#define             G_TYPE_MATCH_INFO
#define             G_TYPE_ARRAY
#define             G_TYPE_BYTE_ARRAY
#define             G_TYPE_PTR_ARRAY
#define             G_TYPE_BYTES
#define             G_TYPE_VARIANT_TYPE
#define             G_TYPE_ERROR
#define             G_TYPE_DATE_TIME
#define             G_TYPE_TIME_ZONE
#define             G_TYPE_IO_CHANNEL
#define             G_TYPE_IO_CONDITION
#define             G_TYPE_VARIANT_BUILDER
#define             G_TYPE_KEY_FILE
#define             G_TYPE_MAIN_CONTEXT
#define             G_TYPE_MAIN_LOOP
#define             G_TYPE_MARKUP_PARSE_CONTEXT
#define             G_TYPE_SOURCE
#define             G_TYPE_POLLFD
#define             G_TYPE_THREAD
typedef             GStrv;

					
何时注册?

 

GBoxed的理解,参考:

http://nanjingabcdefg.is-programmer.com/posts/24152.html

 

 

GEnumValue,GFlagValue

注册2个基础类型:

  1. GEnum
  2. GFlags

Flag和Enum比较类似,Flag可以与bitwise进行位操作

  static const GTypeFundamentalInfo finfo = {

    G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_DERIVABLE,

}; 可派生,可类化;不可深度派生;不可实例化

?为什么要能类化?

GObject的Property会大量用到GEnumValue, GFlagValue, 主要是派生很多;

GParam

(属性)

GObject中Property会用name/value对,来表示某某property;

标准的属性名字和它的值:

/**
 * GParameter:
 * @name: the parameter name
 * @value: the parameter value
 * 
 * The <structname>GParameter</structname> struct is an auxiliary structure used
 * to hand parameter name/value pairs to g_object_newv().
 */
struct _GParameter /* auxillary structure for _setv() variants */
{
  const gchar *name;
  GValue       value;
};

g_param_type_register_static()注册1个基础类型:

GParamSpec

(属性规格)

GParamSpec is an object structure that encapsulates the metadata required to specify parameters, such as e.g. GObject properties.

(主要用于GObject的Properties的元数据的封装)

上面提过属性规格,在Glib中被称作!GParamSpec,它保存了对象的gtype,对象的属性名称,属性枚举ID,属性默认值,边界值等,类型系统用!GParamSpec来将属性的字符串名转换为枚举的属性ID,GParamSpec也是一个能把所有东西都粘在一起的大胶水。
  当咱们须要配置或者获取一个属性的值时,传入属性的名字,并且带上GValue用来保存咱们要配置的值,调用g_object_set/get_property。g_object_set_property函数将在GParamSpec中查找咱们要配置的属性名称,查找咱们对象的类,并且调用对象的set_property要领。这意味着假如咱们要添加一个新的属性,就必须要覆盖默认的set/get_property要领。并且基类包含的属性将被它自身的set/get_property要领所正常处理,因为!GParamSpec就是从基类传递下来的。结尾,应该记得,咱们必须事先议决对象的class_init要领来传入GParamSpec参数,用于安装上属性!

对于这些基本类型,都会提供Gvalue的copied, transformed and compared函数;

用一个全局的数组:

/* --- type initialization --- */
GType *g_param_spec_types = NULL;

来保持这些属性

`GParam (派生22个属性类型)

  |

  +GParamChar  //Char型属性

  |

  +GParamUChar //UChar型属性

  |

  +GParamBoolean

  |

  +GParamInt

  |

  +GParamUInt

  |

  +GParamLong

  |

  +GParamULong

  |

  +GParamInt64

  |

  +GParamUInt64

  |

  +GParamUnichar

  |

  +GParamEnum

  |

  +GParamFlags

  |

  +GParamFloat

  |

  +GParamDouble

  |

  +GParamString

  |

  +GParamParam

  |

  +GParamBoxed

  |

  +GParamPointer

  |

  +GParamValueArray

  |

  +GParamObject

  |

  +GParamOverride

  |

  +GParamGType

  |

  `GParamVariant

每个类型都注册了一组基本的GValue的函数表;

如何来用他们?

GMarshal

列集(Marshaling)是将数据从某种格式存为流格式的操作;

散集(Unmarshaling)则是列集的反操作,将信息从流格式中还原出来。

列集的概念:

http://baike.baidu.com/view/10283079.htm

http://wenku.baidu.com/view/48d00321dd36a32d73758175.html

 

先看这个:

https://developer.gnome.org/gobject/stable/gobject-Closures.html

glib有一些标准的列集函数,在gmarshal.h中定义。例如g_cclosure_marshal_VOID__STRING,

这个函数适合只有一个字符串参数的信号。如果gmarshal.h没有提供适合的列集函数,我们可以用一个叫

glib-genmarshal的工具自动生成列集函数。

 

后面我们会看到,无论是标准列集函数还是生成的列集函数都是既可以用于列集也可以用于散集,这些函数通常都被称作列集函数。

在COM中,Marshalling的作用是对象之间传递数据时:对数据打包和解包。

Marshalling在很多地方都可以用:

  1. 线程之间数据传递时:需要Marshalling 对参数进行转换
  2. 进程之间 (如:dbus的server/client)
  3. 不同语言之间 (如:glib 和Native的C)

信号的列集函数:

http://wenku.baidu.com/view/1e1ae6dfad51f01dc281f186.html

GCClosure

Marshal/closure的关系比较紧密。

https://developer.gnome.org/gobject/stable/gobject-Closures.html

要理解透彻,否则对于很多东西还是一知半解。

GClosure(闭包):表示程序员提供的回调。

GClosure组成:Callback + Marshaller

GClosure的作用:

  1. 调用时,把参数(GValue形式)—> 合适的形式
  2. 调用callback(使用转换过的参数)
  3. 把返回值再à GValue形式

GClosure的一个重要作用是实现Signal机制。

GClosure的好处:不仅仅是callback/data

  1. 允许被调用者(callee)获取callback参数,在多语言绑定时,不用手写glue函数
  2.   blabla
  3.   blabla

 

具体过程:

假设:

Caller: C程序员

Callee: Glib/GObject

 

Step 1: C 程序员定义callback

Step 2: C 程序员提供自己marshal, 或者直接使用glib提供的

Step 3: 定义GCClosure, 并且把callback, marshal注册上去

Step 4: g_closure_invoke()实现 closure的作用(3个)

 

函数指针、回调函数与 GObject 闭包 (写的非常好)

http://garfileo.is-programmer.com/2011/3/20/function-pointer-and-callback-function-and-closure.25453.html

GSignal

在gobject系统中, 信号是一种定制对象行为的手段, 也是一种多种用途的通知机制. 每一个信号都是和能发出信号的类型一起注册到系统中的.
使用 GObject信号机制,一般有三个步骤:

  1. 信号注册, 主要解决信号与数据类型的关联问题
  2. 信号连接, 主要处理信号与闭包的连接问题
  3. 信号发射, 调用callback进行处理

GObject 的信号机制——概览:

http://garfileo.is-programmer.com/2011/3/21/gobject-signal.25477.html

对g_signal_new()参数的解释:

http://nanjingabcdefg.is-programmer.com/posts/24116.html

GObject 信号机制——信号 Accumulator:

http://garfileo.is-programmer.com/2011/3/27/gobject-signal-extra-2.25621.html

GObject

 

 

GPlugin

 

参考:

GObject 学习笔记汇总

http://garfileo.is-programmer.com/categories/6934/posts

快速上手GObject:

http://blog.csdn.net/acs713/article/details/7778051

 

gobjec相关学习文章的list.