小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

淺析GLib

 renhl252 2015-01-09

在 IBM Bluemix 云平臺上開發(fā)并部署您的下一個(gè)應(yīng)用。

現(xiàn)在就開始免費(fèi)試用

GLib需要一個(gè)支持線程的操作系統(tǒng)和一個(gè)字符集間轉(zhuǎn)換函數(shù)iconv的支持,事實(shí)上大多現(xiàn)代的操作系統(tǒng)都有以上兩項(xiàng)功能。

GLib由基礎(chǔ)類型、對核心應(yīng)用的支持、實(shí)用功能、數(shù)據(jù)類型和對象系統(tǒng)五個(gè)部分組成的。

GLib的最新版本是GLib2.2.1,可以到www.gtk.org網(wǎng)站下載其源代碼。使用GLib2.0編寫的應(yīng)用程序,在編譯時(shí)應(yīng)該在編譯命令中加入`pkg-config -cflags -libs glib-2.0`,如編譯一個(gè)名為hello.c的程序,輸出名為hello的可執(zhí)行文件,則命令為:

gcc `pkg-config -cflags -libs glib-2.0`  hello.c -o hello

在GLIB中將線程(gthread),插件(gmoudle)和對象系統(tǒng)(gobject)這三個(gè)子系統(tǒng)區(qū)別對待,編譯時(shí)要注意加入相應(yīng)的參數(shù)。

如程序中用到對象系統(tǒng),編譯時(shí)就應(yīng)加入:

`pkg-config --cflags --libs gobject-2.0`

用到線程,編譯時(shí)則加入:

`pkg-config --cflags --libs gthread-2.0`

用到插件,編譯時(shí)則加入:

`pkg-config --cflags --libs gmoudle-2.0`

基礎(chǔ)類型

GLib的基礎(chǔ)是由基礎(chǔ)類型、范圍限定宏、標(biāo)準(zhǔn)宏、類型轉(zhuǎn)換宏、字節(jié)次序變換宏、數(shù)學(xué)常數(shù)定義和雜項(xiàng)宏等各項(xiàng)組成的。這里主要介紹基礎(chǔ)類型,因?yàn)樗鼈儽榧芭cGLIB相關(guān)的各種程序庫和軟件包中,如GTK+,GNOME,MONO等大的開源項(xiàng)目。

基礎(chǔ)類型又稱標(biāo)準(zhǔn)類型,GLib將C語言中的數(shù)據(jù)類型統(tǒng)一封裝成自己的數(shù)據(jù)類型,均以小寫字母'g'開頭,如:gpointer是指針類型(void *)、guint是無符號整型(unsigned int)等,其中有一些是修飾性的,如:gint、gchar等,它們和C語言中的int、char是完全相同的。這些數(shù)據(jù)類型使用起來和C語言中的數(shù)據(jù)類型完全一樣,當(dāng)你熟悉了以后會(huì)發(fā)現(xiàn)它們的使用方法更靈活,更直觀也更易于理解一些。當(dāng)然你可以把C語言中的數(shù)據(jù)類型直接拿來使用,這絲毫不影響你編寫程序的編譯。

另外范圍限定宏和類型轉(zhuǎn)換宏也較常用,如G_MAXINT表示最大的int型值,用宏GINT_TO_POINTER(i)將整型變量i轉(zhuǎn)換為指針型,宏GPOINTER_TO_INT(p)將指針型變量p轉(zhuǎn)換為整型。

邏輯類型gboolean的值TRUE和FALSE是在常數(shù)宏中定義的,另外還包括G_E表示自然對數(shù),G_PI表示圓周率,G_PI_2表示圓周率的1/2等一些數(shù)學(xué)常數(shù)。

回頁首

對核心應(yīng)用的支持

GLib對核心應(yīng)用的支持包括事件循環(huán)、內(nèi)存操作、線程操作、動(dòng)態(tài)鏈接庫的操作和出錯(cuò)處理與日志等。

下面代碼演示了事件循環(huán)、內(nèi)存操作、線程這三種功能的簡單應(yīng)用:

#include <glib.h>
static GMutex *mutex = NULL;
static gboolean t1_end = FALSE;
static gboolean t2_end = FALSE;
typedef struct _Arg Arg;
struct _Arg
{
	GMainLoop* loop;
	gint max;
};
void	run_1(Arg *arg)
{
	int i ;
	
	for(i=0; i<arg->max; i++)
	{
		if(g_mutex_trylock(mutex) == FALSE)
		{
			//g_print("%d : thread 2 locked the mutex \n", i);
			g_print("%d :線程2鎖定了互斥對象\n", i);
			g_mutex_unlock(mutex);
		}
		else
		{
			g_usleep(10);
		}
	}
	t1_end = TRUE;
}
void	run_2(Arg *arg)
{
	int i;
	for(i=0; i<arg->max; i++)
	{
		if(g_mutex_trylock(mutex) == FALSE)
		{
			//g_print("%d : thread 1 locked mutex \n", i);
			g_print("%d :線程1鎖定了互斥對象\n", i);
			g_mutex_unlock(mutex);
		}
		else
		{
			g_usleep(10);
		}
	}
	t2_end = TRUE;
}
void run_3(Arg *arg)
{
	for(;;)
	{
		if(t1_end && t2_end)
		{
			g_main_loop_quit(arg->loop);
			break;
		}
	}
}
int	main(int argc, char *argv[])
{
	GMainLoop *mloop;
	Arg *arg;
	
	if(!g_thread_supported())
		g_thread_init(NULL);
	mloop = g_main_loop_new(NULL, FALSE);
	
	arg = g_new(Arg, 1);
	arg->loop = mloop;
	arg->max = 11;
		
	mutex = g_mutex_new();
	g_thread_create(run_1, arg, TRUE, NULL);
	g_thread_create(run_2, arg, TRUE, NULL);
	g_thread_create(run_3, arg, TRUE, NULL);
	
	g_main_loop_run(mloop);
	g_print("線程3退出事件循環(huán)\n");
	g_mutex_free(mutex);
	g_print("釋放互斥對象\n"); 
	g_free(arg);
	g_print("釋放參數(shù)所用的內(nèi)存\n");
}

Makefile文件如下:

CC = gcc
all:
	$(CC) `pkg-config --cflags --libs glib-2.0 gthread-2.0` loop.c -o loop

下面為輸出結(jié)果:

0 :線程1鎖定了互斥對象
1 :線程2鎖定了互斥對象
2 :線程1鎖定了互斥對象
3 :線程2鎖定了互斥對象
4 :線程1鎖定了互斥對象
5 :線程2鎖定了互斥對象
6 :線程1鎖定了互斥對象
7 :線程2鎖定了互斥對象
8 :線程1鎖定了互斥對象
9 :線程2鎖定了互斥對象
10 :線程1鎖定了互斥對象
線程3退出事件循環(huán)
釋放互斥對象
釋放參數(shù)所用的內(nèi)存

以上例程創(chuàng)建了三個(gè)線程,其中run_1和run_2操作互斥對象,run_3檢索前兩個(gè)線程是否結(jié)束,如結(jié)束的話,則執(zhí)行g(shù)_main_loop_quit退出事件循環(huán)。由于線程的運(yùn)行是不確定的,所以不一定每次都是這一輸出結(jié)果。

首先定義一個(gè)結(jié)構(gòu)類型來保存創(chuàng)建的事件循環(huán)的對象指針和線程運(yùn)行時(shí)的最多循環(huán)次數(shù),一般情況下,如果為此數(shù)據(jù)結(jié)構(gòu)來分配內(nèi)存的話,用Arg *arg = (Arg *)malloc(sizeof(Arg));,釋放時(shí)用free(arg);,這種傳統(tǒng)的做法曾經(jīng)讓很多C語言的初學(xué)者頭痛,尤其是需要多次操作的時(shí)候,GLib中提供了類似的函數(shù)g_malloc和g_free,最好用的方法是其將g_malloc函數(shù)封裝成了宏g_new,這個(gè)宏有兩個(gè)參數(shù),第一個(gè)是結(jié)構(gòu)類型,第二個(gè)是要分配結(jié)構(gòu)的數(shù)量,這段代碼中只用到了一個(gè)Arg數(shù)據(jù)結(jié)構(gòu),所以是g_new(Arg, 1)。在程序結(jié)束時(shí)用g_free來釋放。

在線程初始化時(shí),首先是判斷線程是否初始化的函數(shù)g_thread_supported,如果其返回FALSE則表明線程并未初始化,這時(shí)必須用g_thread_init來初始化,這是較明智的做法。

事件循環(huán)GMainLoop在用g_main_loop_new創(chuàng)建之后并不馬上運(yùn)行,用g_main_loop_run運(yùn)行后,還要用g_main_loop_quit退出,否則循環(huán)將一直運(yùn)行下去,這兩個(gè)函數(shù)的參數(shù)都是GMainLoop型的指針,在主函數(shù)中并未直接運(yùn)行g(shù)_main_loop_quit,而是把它放在線程的函數(shù)中了,這一點(diǎn)需讀者注意。

回頁首

實(shí)用功能

GLib中包含了近二十種實(shí)用功能,從簡單的字符處理到初學(xué)者很難理解的XML解析功能,這里介紹兩種較簡單的:隨機(jī)數(shù)和計(jì)時(shí)。

下面代碼演示如何產(chǎn)生1-100之間的隨機(jī)整數(shù)和演示如何計(jì)算30000000次累加在計(jì)算時(shí)用的時(shí)間:

/* until.c 用來測試實(shí)用功能 */
#include <glib.h>
int	main(int argc, char *argv[])
{
	GRand *rand;
	GTimer *timer;
	
	gint n;
	gint i, j;
	gint x = 0;
	rand = g_rand_new();	//創(chuàng)建隨機(jī)數(shù)對象
	for(n=0; n<20; n++)
	{	//產(chǎn)生隨機(jī)數(shù)并顯示出來
		g_print("%d\t",g_rand_int_range(rand,1,100));
	}
	g_print("\n");
	g_rand_free(rand);	//釋放隨機(jī)數(shù)對象
	//創(chuàng)建計(jì)時(shí)器
	timer = g_timer_new();
	g_timer_start(timer);//開始計(jì)時(shí)
	for(i=0; i<10000; i++)
		for(j=0; j<3000; j++)
			x++;//累計(jì)
	g_timer_stop(timer);//計(jì)時(shí)結(jié)束
	//輸出計(jì)時(shí)結(jié)果
	g_print("%ld\tall:%.2f seconds was used!\n",x,g_timer_elapsed(timer,NULL));
}

Makefile文件內(nèi)容如下:

CC = gcc all: $(CC) `pkg-config --cflags --libs glib-2.0 ` until.c -o until

輸出結(jié)果:

48 95 95 99 90 24 90 29 78 4 53 87 1 86 7 93 57 88 75 4
30000000 all:1.47 seconds was used!

GLIB中的每個(gè)對象幾乎都有一個(gè)或多個(gè)*_new函數(shù)來創(chuàng)建,計(jì)時(shí)器GTimer和隨機(jī)器GRand也一樣,也都有相對應(yīng)的函數(shù)來結(jié)束對象的使用,如GTimer的g_timer_stop和GRand的g_rand_free。

這可能是GLIB實(shí)用功能中最簡單的兩種了,許多朋友會(huì)一目了然。我們還應(yīng)注意到GLIB的代碼風(fēng)格和封裝技巧是具有獨(dú)到之處的,這種風(fēng)格和技巧足以讓一些自稱簡潔實(shí)用的SDK汗顏,學(xué)習(xí)掌握這一風(fēng)格可能會(huì)讓我們受益匪淺。

回頁首

數(shù)據(jù)類型

GLib中定義了十幾種常用的數(shù)據(jù)結(jié)構(gòu)類型和它們的相關(guān)操作函數(shù),下面是關(guān)于字符串類型的簡單示例:

#include <glib.h>
int	main(int argc, char *argv[])
{
	GString *s;
	s = g_string_new("Hello");
	g_print("%s\n", s->str);
	s = g_string_append(s," World!");
	g_print("%s\n",s->str);
	s = g_string_erase(s,0,6);
	g_print("%s\n",s->str);
	s = g_string_prepend(s,"Also a ");
	g_print("%s\n",s->str);
	
	s = g_string_insert(s,6," Nice");
	g_print("%s\n",s->str);
}

Makefile文件如下:

	CC = gcc
all:
	$(CC) `pkg-config --cflags --libs glib-2.0 ` string.c -o str

下面是輸出結(jié)果:

Hello
Hello World!
World!
Also a World!
Also a Nice World!

字符串在編程中出現(xiàn)頻率之高,即使是初學(xué)者也很清楚,追加、刪除和插入等常用操作理解后,還可以進(jìn)一步了解掌握其它更復(fù)雜的操作。

GLib提供了一種內(nèi)存塊(GMemChunk)數(shù)據(jù)類型,它為分配等大的內(nèi)存區(qū)提供了一種非常好用的操作方式,下面程序演示了內(nèi)存塊數(shù)據(jù)類型的簡單用法:

#include <glib.h>
int	main(int argc, char *argv[])
{
	GMemChunk *chunk;	//定義內(nèi)存塊
	gchar *mem[10];	//定義指向原子的指針數(shù)組
	gint i, j;
	//創(chuàng)建內(nèi)存塊
	chunk = g_mem_chunk_new("Test MemChunk", 5, 50, G_ALLOC_AND_FREE);
				//名稱,原子的長度, 內(nèi)存塊的長度,類型
	for(i=0; i<10; i++)
	{
		//創(chuàng)建對象
		//mem[i] = g_chunk_new(gchar, chunk);
		mem[i] = (gchar*)g_mem_chunk_alloc(chunk);
		for(j=0; j<5; j++)
		{
			mem[i][j] = 'A' + j;//為內(nèi)存塊中的指針賦值
		}
	}
	
	g_mem_chunk_print(chunk);	//顯示內(nèi)存塊信息
	for(i=0; i<10; i++)
	{
		g_print("%s\t",mem[i]);//顯示內(nèi)存塊中的內(nèi)容
	}
	
	for(i=0; i<10; i++)
	{
		g_mem_chunk_free(chunk,mem[i]); //釋放所有分配的內(nèi)存
	}
	g_mem_chunk_destroy(chunk);
}

Makefile文件件如下:

CC = gcc
all:
	$(CC) `pkg-config --cflags --libs glib-2.0` data1.c -o data1

以下為輸出結(jié)果:

GLib-INFO: Test MemChunk: 80 bytes using 2 mem areas
ABCDE	ABCDE	ABCDE	ABCDE	ABCDE	ABCDE	ABCDE	ABCDE	ABCDE	ABCDE

這里說明這一數(shù)據(jù)類型的原因是通過它可以他細(xì)體會(huì)內(nèi)存分配這一運(yùn)行時(shí)處理環(huán)節(jié)的應(yīng)用之妙。

我們在程序中分配的是50字節(jié)的空間,而實(shí)際用的是80字節(jié),由此可以看出其在分配內(nèi)存時(shí)本身用到了部分內(nèi)存空間。

從上面的示例代碼中可以看出,在GLib中幾乎所有的對象都是C語言的結(jié)構(gòu)類型,一般命名以大寫字母G開頭的單詞,如GList表示雙向鏈表,所有與之相關(guān)的操作函數(shù)都以小寫的字母g加下劃線加小寫的單詞加下劃線開頭,如以g_list_*開頭的函數(shù)都是與這相關(guān)的操作函數(shù),而且這些函數(shù)中的第一個(gè)參數(shù)多數(shù)是此對象的指針。

GLIB中的數(shù)據(jù)類型在GLIB本身,尤其是GTK+中頻繁用到,了解掌握這些數(shù)據(jù)類據(jù)類型的用法是非常必要的,這對進(jìn)一步靈活開發(fā)GTK+程序來說是關(guān)鍵一環(huán),而且是對大學(xué)中的《數(shù)據(jù)結(jié)構(gòu)》一科的很好回顧。

在下一篇GOBJECT對象系統(tǒng)中將詳細(xì)介紹GLIB中最重要的組成部分GOBJECT系統(tǒng),希望這一由C語言組建的單繼承的對象系統(tǒng)會(huì)幫助你走進(jìn)GTK+的世界。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多