GLib是一种底层库,创建GDK和GTK应用程序时该库提供许多有用的定义和函数。
包括基本类型及限制的定义、标准宏、类型转化、字节序、存储分配、警告和断言、消息记录、计时器、字符串工具、hook函数、句法扫描器、动态加载模块和字符串自动补全,同时也提供了许多数据类型及相关操作。
包括存储块、双向链表、单向链表、哈希表、动态列表、关系和元组及缓存。最后GLib具有很好的移植性,所以使用GLib作为底层应用支持,那么也保证了应用的可移植性。
类型定义: 1. 整数类型:gint8、guint8、gint16、guint16、gint32、guint32、gint64、guint64。不是所有的平台都提供64位整型 2. 整数类型gshort、glong、gint和short、long、int相同 3. 布尔类型gboolean:gboolean可以取两个值:TRUE和FALSE 4. 字符型gchar和char相同 5. 浮点型gfloat和gdouble和float、double完全等价 6. 指针gpointer对应于标准C的void* 7. gconstpointer对于于标准C的const void*
glib宏: 整型与指针类型间的转换 1. GINT_TO_POINTER(a):将int型转换成gpointer类型 2. GPOINTER_TO_INT(a):将gpointer类型转换成int型 3. GUINT_TO_POINTER(a):将uint类型转换成gpointer类型 4. GPOINTER_TO_UINT(a):将gpointer类型转换成整型 5. NULL宏的定义:#define NULL (void*)0(也就是说:0是一个整型数据,而NULL则是指针类型)
一、双向链表 双向链表中每个元素都包含一块数据和指向前后元素的指针。这使得链表的双向移动变的容易。 存储的数据类型是gpointer,在GLib中,gpointer指向实际数据的指针。 不存在用于创建链表的函数,而是简单的创建一个Glist* 变量,并设置它为NULL。
双向链表中提供的Glib函数:
GList *g_list_append(GList *list, gpointer data):将一个新元素加入到链表尾 GList *g_list_prepend(GList *list, gpointer data):将一个新元素加入到链表头 GList *g_list_insert(GList *list, gpointer data, gint position):插入一个新元素到链表的指定位置 GList *g_list_remove(GList *list, gpointer data):从链表中移除一个具有值data的元素,如果元素不存在,则链表不变 GList *g_list_free(GList *list):数释放由GList使用的所有存储区 GList *g_list_remove_link(GList *list, GList *link) GList *g_list_reverse(GList *list):链表元素位置反转 GList *g_list_nth(GList *list, gint n):获取指定位置元素 GList *g_list_find(GList *list, gpointer data):在链表中查找一个含有指定值的元素,没有则返回NULL GList *g_list_last(GList *list):获取链表中最后一个元素 GList *g_list_first(GList *list):获取链表中第一个元素 gint g_list_length(GList *list):返回链表元素个数 void g_list_foreach(GList *list, GFunc func, gpointer data):遍历链表 gint g_list_index(GList *list, gconstpointer data):返回指定元素在链表中的位置,没有找到匹配的元素,则返回-1。元素位置从0开始计算。
#include <stdio.h> #include <stdlib.h> #include <glib.h> #include <string.h> typedef struct _Teacher { gint age; gchar *name; }Teacher; void each_callback(gpointer data, gpointer user_data) { Teacher *t = (Teacher *)data; g_print("t->name = %s, user param:%s\n" , t->name, ( char *)user_data); } int main( int argc, char *argv[] ) { GList *list = NULL; Teacher *pTeacher1 = g_new0(Teacher,1); pTeacher1->name = g_new0(char ,128); strcpy(pTeacher1->name,"tiny Jason" ); list = g_list_append(list, pTeacher1); Teacher *pTeacher2 = g_new0(Teacher,1); pTeacher2->name = g_new0(char ,128); strcpy(pTeacher2->name,"Rorash" ); list = g_list_prepend(list, pTeacher2); Teacher *pTeacher3 = g_new0(Teacher,1); pTeacher3->name = g_new0(char ,128); strcpy(pTeacher3->name,"alibaba" ); list = g_list_prepend(list, pTeacher3); g_list_foreach(list, each_callback, "user_data" ); GList *second = g_list_find(list, pTeacher2); if (second != NULL) { Teacher* t = (Teacher*)second->data; g_print("name :%s\n" ,t->name); } list = g_list_remove(list, pTeacher2); g_list_foreach(list, each_callback, "user_data" ); gint len = g_list_length(list); g_print("len :%d\n" ,len); GList *nNode = g_list_nth(list,1); if (nNode != NULL) { Teacher* t = (Teacher*)nNode->data; g_print("name :%s\n" ,t->name); } g_list_free(list); return 0; }
makefile:
.SUFFIXES:.c .o CC=gcc SRCS=test_glib.c OBJS=$(SRCS:.c=.o) EXEC=test_glib all:$(OBJS) $(CC) -o $(EXEC) $(OBJS) `pkg-config --libs glib-2.0` .c.o: $(CC) -o $@ -c -g $< `pkg-config --cflags glib-2.0` clean: rm -f $(OBJS)
运行结果:
t->name = alibaba, user param:user_data t->name = Rorash, user param:user_data t->name = tiny Jason, user param:user_data name :Rorash t->name = alibaba, user param:user_data t->name = tiny Jason, user param:user_data len :2 name :tiny Jason
二、单向链表
GSList *g_slist_append(GSList *list, gpointer data):链表最后新增一个元素 GSList *g_slist_prepend(GSList *list, gpointer data):链表最前面新增一个元素 GSList *g_slist_insert(GSList *list, gpointer data, gint position):指定链表位置插入新元素 GSList *g_slist_remove(GSList *list, gpointer data):链表中删除具有值data的元素 GSList *g_slist_reverse(GSList *list):反转元素位置 GSList *g_slist_nth(GSList *list, gint n):返回链表中下一个元素 GSList *g_slist_find(GSList *list, gpointer data):查找指定data的元素,没有则返回NULL GSList *g_slist_last(GSList *list):查找链表的最后一个元素 gint g_slist_length(GSList *list):返回链表元素个数 void g_slist_foreach(GSList *list, GFunc func, gpointer data):遍历链表
三、存储管理
gpointer g_malloc(gulong size):这是malloc的替代函数,不需要检查返回值。如果存储分配因任何原因失败,则应用程序终止。 gpointer g_malloc0(gulong size):和g_malloc具有相同功能,但在返回指向分配存储块的指针前,将该存储块清0。 gpointer g_realloc(gpointer mem, gulong size):重新分配由mem开始的指针,并设置大小为size字节。 void g_free(gpointer mem):释放分配的存储块。如果mem为NULL,则直接返回。
四、计时器
计时器函数可用于记录操作记时,也可以记录程序的间断运行时间。
GTimer *g_timer_new( void ):创建一个新计时器 void g_timer_destroy(GTimer *timer):注销计时器 void g_timer_start(GTimer *timer):计时器开始 void g_timer_stop(GTimer *timer):停止计时 void g_timer_reset(GTimer *timer):重置计时器 void g_timer_continue(GTimer *timer):继续计时 gdobule g_timer_elapsed(GTimer *timer, gulong *microseconds):决定所耗时间
Example:
GTimer *timer; void each_callback(gpointer data, gpointer user_data) { g_print("element:%s, user param:%s\n" , (gchar*)data, (gchar*)user_data); } int main( int argc, char *argv[] ) { GList *list = NULL; gulong seconds; int i=0; timer = g_timer_new(); list = g_list_append(list, "second" ); list = g_list_prepend(list, "first" ); g_timer_start(timer); g_list_foreach(list, each_callback, "user_data" ); g_timer_stop(timer); g_timer_elapsed(timer, &seconds); g_print("use seconds:%ld\n" , seconds); g_timer_continue(timer); for (i; i<=1000; i++) { g_print("%d" , i); } g_timer_elapsed(timer, &seconds); g_print("use seconds:%ld\n" , seconds); return 0; }
五、字符串处理
编程中经常需要对字符串进行拼接、截取、大小写转换,原本在C中这些操作是非常繁琐的。现在GLib定义了一个叫做GString的新类型,它可以自动增长,并且提供了 一系列方便的操作函数。 struct GString{ gchar *str;/*指向当前以\0结尾的字符串*/ gint len;/*当前字符长度*/ }
GString *g_string_new(gchar *init):创建GList类型 GString *g_string_truncate(GString *string, gint len):截取指定长度的字符串 GString *g_string_append(GString *string, gchar *val):末尾追加字符串 GString *g_string_append_c(GString *string, gchar c):末尾最加单个字符 GString *g_string_prepend(GString *string, gchar *val):开头插入字符串 GString *g_string_prepend_c(GString *string, gchar c):开头插入单个字符 void g_string_sprintf(GString *string, gchar *fmt, ...):格式化字符串 gchar *g_strdup (const gchar *str):复制字符串,返回一个新分配的字符串。 gchar *g_strndup(const gchar *str, gsize n):复制指定个数的字符串,返回新分配的字符串 gchar *g_strstr_len(const gchar *haystack, gssize haystack_len, const gchar *needle):在限定长度内,第一次出现指定字符的指针 gchar *g_strrstr(const gchar *haystrack, const gchar *needle):搜索字符串haystack中最后一次出现的串针。 gchar *g_strrstr_len(const gchar *haystrack, gssize haystrack_len, const gchar *needle) gboolean g_str_hash_prefix(const gchar *str, const gchar *prefix):返回字符串是否以某个前缀开头 int g_strcmp0( const char *str1, const char *str2):对比两个字符串 gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens):分割字符串,保存为数组 gchar *g_strconcat(const gchar *string1, ...):字符串拼接 gchar *g_strjoin(const gchar *separator, ...):以某个字符串隔离并拼接
更多
http://gtk-doc-cn.googlecode.com/svn/docs/glib/glib-String-Utility-Functions.html#g-strdup
六、错误处理
gchar *g_strdup( const gchar *str ):替代strdup函数。把原字符串内容复制到新分配的存储块中,返回指向它的指针。 gchar *g_strerror( gint errnum ); void g_error( gchar *format, ... );错误提示:“ ** ERROR ** ”并且退出程序。仅用在致命错误上。 void g_warning( gchar *format, ... ):错误提示:“ ** WARNING ** ” void g_message( gchar *format, ... ):在传递字符串前打印 "message" void g_print( gchar *format, ... ):替代printf函数
除了上述之外,GLib还提供了很多功能,包括编码转换、正则、XMP解析、Test框架等等。
glib about thread,mutex,cond
#include <glib.h> #include <stdio.h> static int num = 0; GMutex mutex; GCond cond; gboolean _thread_main1(void *data) { while (1) { g_mutex_lock(&mutex); while (num <= 0) { g_printf("consumer[%d] is wating.....\n" ,( int )data); g_cond_wait(&cond, &mutex ); g_printf("consumer[%d] wake up.....\n" ,( int )data); } g_printf("consmuer[%d] before,num = %d.....\n" ,( int )data,num); num--; g_printf("consmuer[%d] after,num = %d.....\n" ,( int )data,num); g_mutex_unlock(&mutex); sleep(1); } return TRUE; } gboolean _thread_main2(void *data) { while (1) { g_mutex_lock(&mutex); num++; if (num > 0) { g_printf("prepare to sigal...please wait for 5 seconds\n" ); sleep(5); g_cond_signal(&cond); g_printf("after g_cond_signal\n" ); } g_mutex_unlock(&mutex); sleep(2); } return TRUE; } int main( int argc, char *argv[] ) { GThread *consumer1 = NULL; GThread *consumer2 = NULL; GThread *consumer3 = NULL; GThread *thread2 = NULL; g_mutex_init(&mutex); g_cond_init( &cond ); consumer1 = g_thread_new("consumer1" , (GThreadFunc)_thread_main1, ( void *)1); consumer2 = g_thread_new("consumer2" , (GThreadFunc)_thread_main1, ( void *)2); consumer3 = g_thread_new("consumer3" , (GThreadFunc)_thread_main1, ( void *)3); thread2 = g_thread_new("thread2" , (GThreadFunc)_thread_main2, NULL); g_thread_join (consumer1); g_thread_join (consumer2); g_thread_join (consumer3); g_thread_join (thread2); return 0; }
结果:
consumer[1] is wating..... consumer[2] is wating..... prepare to sigal...please wait for 5 seconds after g_cond_signal consumer[1] wake up..... consmuer[1] before,num = 1..... consmuer[1] after,num = 0..... consumer[3] is wating..... consumer[1] is wating..... prepare to sigal...please wait for 5 seconds after g_cond_signal consumer[2] wake up..... consmuer[2] before,num = 1..... consmuer[2] after,num = 0..... consumer[2] is wating..... prepare to sigal...please wait for 5 seconds after g_cond_signal consumer[3] wake up..... consmuer[3] before,num = 1..... consmuer[3] after,num = 0..... consumer[3] is wating..... prepare to sigal...please wait for 5 seconds after g_cond_signal consumer[1] wake up..... consmuer[1] before,num = 1..... consmuer[1] after,num = 0..... consumer[1] is wating..... prepare to sigal...please wait for 5 seconds after g_cond_signal consumer[2] wake up..... consmuer[2] before,num = 1..... consmuer[2] after,num = 0..... consumer[2] is wating.....