Gobject 時(shí)一個(gè)為C語(yǔ)言提供面向?qū)ο缶幊痰幕A(chǔ)庫(kù)蹲坷。 作為一門基礎(chǔ)語(yǔ)言坷剧,C語(yǔ)言在操作系統(tǒng)層面有著絕對(duì)統(tǒng)治的應(yīng)用浦夷,但是它是一門過(guò)程語(yǔ)言懊渡,在面對(duì)業(yè)務(wù)處理上,由于缺乏足夠的抽象军拟,編寫起來(lái)非常費(fèi)力剃执。為了減少這些缺陷,C語(yǔ)言生態(tài)圈也出現(xiàn)了不同的基礎(chǔ)庫(kù)懈息,幫助想使用面向?qū)ο筮M(jìn)行C語(yǔ)言開發(fā)的工程師進(jìn)行開發(fā)肾档,Gobject就是其中之一。
在面向?qū)ο蟮恼Z(yǔ)言里辫继,每一個(gè)事物或者業(yè)務(wù)會(huì)被抽象為一種類型怒见,每一個(gè)具體的事物都是這個(gè)類的實(shí)例。在聲明和創(chuàng)建一個(gè)方法通常用下面的格式:
VcamSource source=new VcamSouce(......);
在Gobject中姑宽,通常會(huì)這樣寫:
VcamSource *source遣耍;
source=g_object_new(VCAM_TYPE_SOURCE, NULL);
VCAM_TYPE_SOURCE 是一個(gè)宏定義,用來(lái)返回系統(tǒng)中注冊(cè)的VcamSource類型炮车。
在面向?qū)ο蟮恼Z(yǔ)言里因?yàn)橛袕?fù)雜的對(duì)象與類繼承管理舵变,所以通常只需要聲明VcamSource 類就可以了:
Class VcamSource{
public:
....
private:
.....
}
在C語(yǔ)言中是缺乏這些的酣溃,所以Gobject提供類自己的繼承鏈和類型注冊(cè)系統(tǒng),在Gobject中纪隙,我們通常需要聲明一個(gè)抽象類型和它的類型描述類:
#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H
#include <glib-object.h>
#define VCAM_TYPE_SOURCE (vcam_source_get_type ())
//抽象類型
typedef struct _VcamSoure VcamSource;
struct _VcamSoure {
GObject parent_instance;
};
//抽象類型的類
typedef struct _VcamSoureClass VcamSourceClass;
struct _VcamSoureClass {
GObjectClass parent_class;
};
GType vcam_source_get_type(void);
#endif
可以看出VcamSource抽象類型其實(shí)就是一個(gè)struct 結(jié)構(gòu)體赊豌, 它包含至少一個(gè)屬性GObject parent_instance;, 這表示的是一個(gè)繼承關(guān)系: VcamSource繼承自 GObject (這個(gè)屬性必須為第一個(gè)元素)绵咱。
_VcamSoureClass 是VcamSource的類型碘饼,它用來(lái)描述VcamSource和包含這一個(gè)類事務(wù)的通用屬性或方法。它的第一個(gè)屬性是GObjectClass悲伶,也表示的是繼承關(guān)系艾恼,且 GObjectClass正是GObject的類。
在這個(gè)定義中麸锉,宏定義VCAM_TYPE_SOURCE對(duì)應(yīng)的是一個(gè)返回GType 類型的方法蒂萎,他正對(duì)應(yīng)Gobject創(chuàng)建實(shí)例的第一個(gè)參數(shù):
source=g_object_new(VCAM_TYPE_SOURCE, NULL);
VCAM_TYPE_SOURCE實(shí)際上是vcam_source_get_type()方法的調(diào)用; 這個(gè)方法主要做兩件事情:聲明一個(gè)VcamSource的Gtype類型淮椰;把這個(gè)類型發(fā)注冊(cè)到Gobject的類型系統(tǒng)里五慈,這樣才可以通過(guò)g_object_new來(lái)初始化。它的具體實(shí)現(xiàn)是在VcamSource.c文件里主穗;vcam_source_get_type的實(shí)現(xiàn)內(nèi)容大概如下:
GType vcam_source_get_type(void)
{
static GType source_type = 0;
if (!media_type)
{
//聲明一個(gè)GTypeInfo類型
static const GTypeInfo source_info = {
sizeof(VcamSourceClass), /* class structure size */
NULL, /* base class initializer */
NULL, /* base class finalizer */
(GClassInitFunc)VcamSource_class_init, /* class initializer */
NULL, /* class finalizer */
NULL, /* class data */
sizeof(VcamSource), /* instance structure size */
16, /* preallocated instances */
NULL, /* instance initializer */
NULL /* function table */
};
//將GTypeInfo info注冊(cè)到Gobject的type系統(tǒng)里
media_type = g_type_register_static(
G_TYPE_OBJECT, /* parent class */
"Media", /* type name */
&media_info, /* GTypeInfo struct (above) */
0); /* flags */
}
return source_type ;
}
g_type_register_static(parent_id, name, type_info, options) 用于類型的注冊(cè)泻拦,他的參數(shù)如下:
parent_id: 父類標(biāo)識(shí),Object類的標(biāo)識(shí)就是通過(guò)G_TYPE_OBJECT宏獲取
name: 類型名稱
typeinfo: GTypeInfo結(jié)構(gòu)忽媒,里面包含了對(duì)新類型的描述
options: 標(biāo)識(shí)符争拐,例如標(biāo)準(zhǔn)虛類等。
在看一下晦雨,source_info的聲明架曹,里面包含了很多內(nèi)容,我們需要了解的包含基礎(chǔ)類的初始化闹瞧,class類型的初始化绑雄,實(shí)例的初始化等等。這些方法的聲明如下:
typedef void (GBaseInitFunc) (gpointer g_class);
typedef void (GBaseFinalizeFunc) (gpointer g_class);
typedef void (GClassInitFunc) (gpointer g_class, gpointer class_data);
typedef void (GClassFinalizeFunc) (gpointer g_class, gpointer class_data);
typedef void (*GInstanceInitFunc) (GTypeInstance *instance, gpointer g_class);
如果要一個(gè)一個(gè)實(shí)現(xiàn)奥邮,確實(shí)也是很費(fèi)勁的事情万牺,GObject也考慮了這一點(diǎn),所以提供了一個(gè)新的宏定義洽腺,它是聲明在.c文件里:
#include "VcamSource.h"
G_DEFINE_TYPE(VcamSource, vcam_source, G_TYPE_OBJECT)
static void
vcam_source_class_init(VcamSourceClass* class) { //類初始化方法
}
static void
vcam_source_init(VcamSource* d) { //實(shí)例初始化方法
}
int main(int argc, char** argv) {
GType dtype;
VcamSource* d;
dtype = vcam_source_get_type(); /* or d = T_TYPE_DOUBLE */
if (dtype)
g_print("Registration was a success. The type is %lx.\n", dtype);
else
g_print("Registration failed.\n");
return 0;
}
G_DEFINE_TYPE是在.c文件里出現(xiàn)的脚粟,他做了以下的工作:
- 聲明了一個(gè)新類型的類的初始化函數(shù),格式為<name space>_<name>_class_init 我們通常需要這個(gè)方法來(lái)注冊(cè)屬性蘸朋、掛載虛函數(shù)核无。
- 聲明了一個(gè)新類型的初始化函數(shù),格式為 <name space>_<name>_init藕坯,我們通常在這個(gè)函數(shù)中初始化具體實(shí)例的信息团南。
- 聲明了一個(gè)靜態(tài)變量噪沙,讓它指向新類型的類的父類。 格式為 <name space>_<name>_parent_class已慢,可用于訪問(wèn)父類中的方法曲聂。
- 定義了獲取類ing的函數(shù)霹购,格式為<name space>_<name>_get_type ()佑惠,這個(gè)正是我們注冊(cè)類型需要的,所以GType vcam_source_get_type(void);這一行在頭文件中就可以省略了齐疙。
G_DEFINE_TYPE很顯然簡(jiǎn)化了我們的大量工作膜楷,但是要注意遵循對(duì)初始化函數(shù)的命名規(guī)范。
在面向?qū)ο蟮恼Z(yǔ)言里贞奋,通常我們需要類型映射赌厅,需要檢查某個(gè)實(shí)例是否試我們想要的類型,類似于:
source2 =VcamSoure(obj);
obj instanceof VcamSoure;
在Object里轿塔,同樣使用宏定義來(lái)實(shí)現(xiàn)前兩項(xiàng):
#defind VCAM_SOURCE(obj) ....
#defind VCAM_IS_SOURCE(obj) ....
這有需要在.h加入很多行特愿,于是為了更簡(jiǎn)潔, Gobject 提供了一個(gè)新的宏 G_DECLARE_FINAL_TYPE, 它可以做下面這些事情:
- 聲明了一個(gè)<name space>_<name>_get_type ()方法勾缭,而G_DEFINE_TYPE包含了對(duì)它的定義揍障,所以我們實(shí)際上跟本不需要寫這個(gè)方法。
- 定義了一個(gè)有用的宏<NAME SPACE>_<NAME>俩由,用來(lái)進(jìn)行對(duì)象的映射毒嫡。例如 VCAM_SOURCE(object)可以把普通對(duì)象類映射成我們需要的VcamSource類。
- 定義了一個(gè)<NAME SPACE>IS<NAME>幻梯, 用來(lái)判斷是否一個(gè)實(shí)例來(lái)自于我們想要的類型兜畸。例如,VCAM_IS_SOURCE(obj), 可以判斷 obj是否是VcamSource的實(shí)例碘梢。
于是咬摇,引入這個(gè)宏后,我們的.h文件就更簡(jiǎn)潔了:
#ifndef VCAM_SOURCE_H
#define VCAM_SOURCE_H
#include <glib-object.h>
#define VCAM_TYPE_SOURCE (vcam_source_get_type())
G_DECLARE_FINAL_TYPE(VcamSource, vcam_source, VCAM, SOURCE, GObject)
struct _VcamSoure {
GObject parent_instance;
};
struct _VcamSoureClass {
GObjectClass parent_class;
};
#endif /* __VCAM_SOURCE_H__ */
但是宏G_DECLARE_FINAL_TYPE有個(gè)缺陷煞躬,它不允許有任何子對(duì)象菲嘴,相當(dāng)于用Final修飾了VcamSoure 。如果需要有子對(duì)象汰翠,就需要使用另外一個(gè)宏G_DECLARE_DERIVABLE_TYPE 龄坪。