Glib入门学习笔记
2021-01-04 14:31:22 阿炯

本站赞助商链接,请多关照。 Glib是一种底层库,创建 GDK 和 GTK 应用程序时该库可提供许多有用的定义和函数。它们包括基本类型及限制的定义、标准宏、类型转换、字节序、存储分配、警告和断言、消息记录、计时器、字符串 工具 (string utilities)、挂钩 (hook) 函数、一个句法扫描器、动态加载模块和自动字符串补全,它也定义了许多数据结构(及其相应的操作),包括存储块、双向链表、单向链表、哈希表、串(动态增 长)、串块(串的组)、数组(大小可随元素的加入而增长)、平衡二叉树、N 叉树、夸克 (quark,一种字符串和其唯一的整数标识之间的双向关联)、键数据列表(可由字符串或整数标识访问的数据元素列表)、关系和元组(可通过任一位置号索引的数据表格)以及缓存 (cache)。

在开源世界中,G中很常见的。它代表了GNU (GNU's Not Unix)。像GTK+,GLib,GObject,以及GNOME,还有一些其它的软件包,如Ghostscript和gcc中都充满了G。

必须学习一些GLib的基础知识(libglib-2.0),它为GTK+和GNOME程序提供了基础的数据结构和实用函数。在此会涉及到GLib的结构和API的介绍,同时将会在后面学习GLib's object system(GObject)。在使用GNOME和GTK+的时候,会不可避免的使用GLib,GLib所提供的库和实用工具为编程提供了方便,而且很容易移植到其它平台。

GLib Naming Coventions (GLib命名规则)

就像许多其它的库一下,GLib也为了一致性和易读性规范了命名规则。函数的名字一般都是小写的,并且在每部分名字之间加下划线,如g_timer_new(),g_list_append()。并且所有的函数名字都是以g_开头。

在GLib中,所有的函数都有前缀g_。类型名并不包含下划线,并且GLib里面的所有类型组件都是以大写字母G开头的,如GTimer,GList。但GLib中的基本类型是值得注意的例外。如果某个函数主要是操作某个特定的类型的话,这个函数的前缀就与相应的类型相匹配。例如,g_timer_*就是操作GTimer类型。g_list_*就是操作GList类型。这些规则听起来比实际要复杂。

下面将总结Glib库函数的一些功能,没有包括所有函数,数据结构或操作。有关Glib库的更完整的信息请看 Glib 文档,也可以从GTK的主站上下载得到。
 

1、标准类型定义

许多标准类型的极值定义是:
G_MINFLOAT
G_MAXFLOAT
G_MINDOUBLE
G_MAXDOUBLE
G_MINSHORT
G_MAXSHORT
G_MININT
G_MAXINT
G_MINLONG
G_MAXLONG
 
下面的 typedefs 也是定义,余下未定义的则根据硬件平台的不同而动态设置。请记住如果要想使程序具有可移植性就不要计算指针的大小。一个指针在 Alpha 上是 8 个字节,而在 Intel 80x86 系列 cpu 上是 4 个字节。

char   gchar;
short gshort;
long   glong;
int    gint;
char   gboolean;

unsigned char   guchar;
unsigned short gushort;
unsigned long   gulong;
unsigned int    guint;

float   gfloat;
double gdouble;
long double gldouble;

void* gpointer;

gint8
guint8
gint16
guint16
gint32
guint32


Basic Types 基本类型讲解1

在开始使用 GLib 之前,首先要适应 GLib 的基本类型。或许很想知道为什么使用 guchar 要比使用 unsigned char 好。如果程序一直待在同一个平台上执行,那么使用 guchar 与使用 unsigned char 并没有实质的差别。但如果想编写出在不同平台之间移植的程序,如 Windows 和 Unix 之间。那就会很感谢 GLib 将基本类型给抽象出来了。

例如想在所有可能的平台上定义 16 位的无符号整型,使用 C 语言的话可能看起来很麻烦。但幸运的是 GLib 帮忙处理了这些。所有的基本类型在下面的表格中列出。

要使用 GLib 和它的类型,必须要在源码中包含 glib.h:
#include <glib.h>

gpointer 和 gconstpointer 类型在 GLib 的数据结构中经常出现,这两个是无类型的内存指针。在 GLib 中,函数负责检查这两个指针的类型,程序员和编译器并不管这些。这在回调函数以及排序和遍历中比较的时候尤其方便。

在 GLib 的头文件中为 gboolean 类型定义了 TRUE 和 FALSE 常量。在使用这些常量的时候,不要使用比较运算符。例如要用:if (my_gboolean) ,而不是:if (my_gboolean == TRUE) 。

GLib Type

Corresponding Type in C

gchar

char

ugchar

unsigned char

gint

int

guint

unsigned int

gshort

short

gushort

unsigned short

glong

long

gulong

unsigned long

gfloat

float

gdouble

double

gint8

int, 8 bits wide

guint8

unsigned int, 8 bits wide

gint16

int, 16 bits wide

guint16

unsigned int, 16 bits wide

gint32

int, 32 bits wide

guint32

unsigned int, 32 bits wide

gint64

int, 64 bits wide

guint64

unsigned int, 64 bits wide

gpointer

void *, untyped pointer

gconstpointer

const void *, constant untyped pointer

gboolean

Boolean value, either TRUE or FALSE



Basic Utilities

( 基本函数 , 这个 Utilities 不知道如何译,就写成函数吧,因为后面确实在讲函数…… )为了简化程序与 C 语言以及系统的交互,GLib 提供了大量的函数。要了解 GLib 的函数处理数据结构部分,请看后面章节。


注意: 如果有一些特殊的原因要使用函数的返回值的话,可以使用 g_try_malloc() 和 g_try_realloc() ,如果出错的时候,它们会返回 NULL 。这可以在某些不是非常关键的地方使用 ( 如某些用来提高性能的额外缓冲区 ) ,或者某些测试的时候。

如果想覆盖 GLib 的保护机制,必须要清楚在做什么。对大多数程序来说,这些像 g_malloc() 的普通函数能节约大量的代码、错误、以及时间。

一般情况下,没有必要为 malloc 或 g_malloc 指定具体的要申请的块的大小。一般都是使用 sizeof() 来告诉编译器或运行时系统申请某种类型的某个倍数。为了与数据类型相符,必须要将 malloc() 返回值进行强制转换。强制转换要用大量的括号和星号,所以 GLib 提供了一些宏,如 g_new(),g_new0() 以及 g_renew() 。


内存管理

如果使用 GLib 提供的内存管理例程,它可以避免你处理很多让你头痛的事。GLib 提供了的附加的错误检查与侦测,在下面的表格中为 C 程序员提供了一个参考。可以使用 g_malloc(),g_realloc(),g_free() 来代替 malloc(),realloc(),free(),它们提供了相同的处理方式。为了将申请的内存在使用前清零,可以使用 g_malloc0() 。 注意,它的语法看起来像 malloc ,而不是 calloc() 。

GLib Function

Corresponding C Function

gpointer g_malloc(gulong n_bytes)

void *malloc(size_t size) with error handling

gpointer g_malloc0(gulong n_bytes)

like malloc(), but initializes memory as in calloc()

gpointer g_try_malloc(gulong n_bytes)

like malloc() without error checking

gpointer g_realloc(gpointer mem, gulong n_bytes)

void *realloc(void *ptr, size_t size) with error checking

gpointer g_try_realloc(gpointer mem, gulong n_bytes)

realloc() without error checking

void g_free(gpointer mem)

void free(void *ptr)


内存块

GUI 程序一般倾向于重复申请大小相同的内存块 (原子) 。而且,那儿有一些相关的原子内存 (atom) 。 GLib 使用了一种称为“ memory chunks ”的方法为程序提供了相应的原子内存。一个内存块由一些原子内存组成的;所以块的大小肯定是原子内存大小的整数倍。


Quarks (夸克)

为了在程序中标识一块数据,一般有两种方式可选:数字或字符串。但是这两者都有一些缺点。数字是非常难以辨认的。如果开始粗略的知道需要多少标签,就可以定义一个枚举类型和一些字符符号。但是没法在运行的时候动态添加标签。

另一方面,可以在运行的时候动态的添加或修改字符串,而且它们是很容易理解的。但是字符串比较要比数字比较花更长的时间,而且在内存中管理字符串有一些你可能不愿意处理的额外麻烦。GLib 提供了 GQuark 类型,它整合了数字的简单和字符串的易用。在它内部,它就是一个易于比较和复制的整形数。GLib 将这些数字映射为字符串,并且可以在任何时间取得字符串所对应的值。


Basic Types 基本类型讲解2

基本类型 — 标准的Glib类型,定义的非常易用和简便。

#include <glib.h>
typedef             gboolean;
typedef             gpointer;
typedef             gconstpointer;
typedef             gchar;
typedef             guchar;

typedef             gint;
typedef             guint;
typedef             gshort;
typedef             gushort;
typedef             glong;
typedef             gulong;

typedef             gint8;
typedef             guint8;
typedef             gint16;
typedef             guint16;
typedef             gint32;
typedef             guint32;

#define             G_HAVE_GINT64
typedef             gint64;
GLIB_VAR            guint64();
#define             G_GINT64_CONSTANT(val)
#define             G_GUINT64_CONSTANT(val)

typedef             gfloat;
typedef             gdouble;

typedef             gsize;
typedef             gssize;
typedef             goffset;

Description 描述
定义一些普通使用类型,可分为4组:
1.不属于标准C的新类型:gboolean, gsize, gssize.

2.可以在任何平台使用的整数:gint8, guint8, gint16, guint16, gint32, guint32, gint64, guint64.

3.与标准C相似但更好用的类型:gpointer, gconstpointer, guchar, guint, gushort, gulong.

4.与标准C基本一致的类型:gchar, gint, gshort, glong, gfloat, gdouble.

Details 详细说明
gboolean
typedef gint gboolean;
标准的boolean类型。它只储存两个值:TRUE和FALSE

gpointer
typedef void* gpointer;
无类型的指针。Gpointer比 void*更好看和更好用。

gconstpointer
typedef const void *gconstpointer;
一个常数的无类型指针。指针的值不能被更改。典型的使用子函数原型上,指出指针所指向的数据是不能被函数更改的。

gchar
typedef char   gchar;
和标准C的char类型一致。

guchar
typedef unsigned char   guchar;
和标准C的 unsigned char一致。

gint
typedef int    gint;
类似标准C的int类型。其值能被设置G_MININT 到 G_MAXINT范围。

guint
typedef unsigned int    guint;
类似标准C的unsigned int类型。其值能被设置0到 G_MAXUINT的范围。

gshort
typedef short  gshort;
类似标准C的short类型。其值能被设置G_MINSHORT 到 G_MAXSHORT范围。

gushort
typedef unsigned short  gushort;
类似标准C的unsigned short类型。其值能被设置0到 G_MAXUSHORT的范围。

glong
typedef long   glong;
类似标准C的long类型。其值能被设置G_MINLONG 到 G_MAXLONG范围。

gulong
typedef unsigned long   gulong;
类似标准C的unsigned long类型。其值能被设置0到 G_MAXULONG的范围。

gint8
typedef signed char gint8;
在任何平台上都保证是一个有符号8位整数。其取值返回为 -128 到 127

guint8
typedef unsigned char guint8;
在任何平台上都保证是一个无符号8位整数。其取值返回为 0 到 255

gint16
typedef signed short gint16;
在任何平台上都保证是一个有符号16位整数。其取值返回为 -32,768 到 32,767

guint16
typedef unsigned short guint16;
在任何平台上都保证是一个无符号16位整数。其取值返回为 0 到 65,535

gint32
typedef signed int gint32;
在任何平台上都保证是一个有符号32位整数。其取值返回为 -2,147,483,648 到 2,147,483,647

guint32
typedef unsigned int guint32;
在任何平台上都保证是一个无符号32位整数。其取值返回为 0 到 4,294,967,295

gint64
G_GNUC_EXTENSION typedef signed long long gint64;
在任何平台上都保证是一个有符号64位整数。其取值返回为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807

guint64()
GLIB_VAR guint64();
在任何平台上都保证是一个无符号32位整数。
其取值返回为 0 到 18,446,744,073,709,551,615

G_GINT64_CONSTANT()
#define G_GINT64_CONSTANT(val)  (G_GNUC_EXTENSION (val##LL))
This macro is used to insert 64-bit integer literals into the source code.
val :  a literal integer value, e.g. 0x1d636b02300a7aa7U.

G_GUINT64_CONSTANT()
#define G_GUINT64_CONSTANT(val)  (G_GNUC_EXTENSION (val##ULL))
This macro is used to insert 64-bit unsigned integer literals into the source code.

val :  a literal integer value, e.g. 0x1d636b02300a7aa7U.
Since 2.10

gfloat
typedef float   gfloat;
类似标准C的float类型。其值可以设置-G_MAXFLOAT 到 G_MAXFLOAT范围

gdouble
typedef double  gdouble;
类似标准C的double类型。其值可以设置-G_MAXDOUBLE 到G_MAXDOUBLE范围

gsize
typedef unsigned int gsize;
一个无符号整形,用来储存sizeof的结果,与C99的size_t类型类似。这个类型能足够存储下一个指针的数据。它常常在32为平台上是32位的,在64位平台上是64位的。

gssize
typedef signed int gssize;
一个有符号gsize,与大多数平台的ssize_t类型类似。

goffset
typedef gint64 goffset;
一个有符号的整形,用来作为文件偏移。类似于C99的off64_t
Since: 2.14


2、双向链表

以下的函数用于创建、管理和销毁标准双向链表。链表中每个元素都包含一块数据和指向前后元素的指针。这使得通过链表的双向移动变的容易。数据项的类型是"gpointer",意指数据可为一指向实际数据的指针或 (通过类型转换) 为一数值(但不要设想 int 和 gpointer 有相同的大小!)。这些函数在内部按块为链表元素分配空间,这比单为每个元素分配空间更有效率。
 
不存在专用于创建列表的函数。而是简单地创建一个类型为 Glist* 的变量,并把它的值设置为 NULL;NULL被当作空表。
 
向链表中加入一个新元素,使用函数 g_list_append()、g_list_prepend()、g_list_insert() 或 g_list_insert_sorted()。无论如何,函数都接收一个指向表头的指针作为参数,并返回一个指向表头的指针(可能和接收的指针不同)。因此,对所有添加或撤除链表元素的操作,一定要保存返回值!

GList *g_list_append( GList *list, gpointer data );

此函数把一个新元素(具有值data)加到链表尾。

GList *g_list_prepend( GList *list, gpointer data );

此函数把一个新元素(具有值data)加到链表头。

GList *g_list_insert( GList *list, gpointer data, gint position);

此函数插入一个新元素(具有值data)到链表中指定位置,如果位置是 0,它和g_list_prepend() 函数作用相同,如果位置,它和 g_list_append() 函数作用相同。

GList *g_list_remove( GList *list, gpointer data);
此函数从表中移除一个具有值data的元素,如果该元素不存在,链表不变。
 
void g_list_free( GList *list );
此函数释放由Glist使用的所有存储区,如果表元素空间是通过动态分配的,则应首先被释放。

还有许多其它支持双向链表的Glib函数;查看文档获得更多的信息。这儿列出几个更有用的函数的声明:
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 );

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 user_data );


3、单向链表
 
以上的许多函数用于单向链表是一样的。下面是链表操作函数的部分列表:

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 );

GSList *g_slist_remove_link( GSList *list, GSList *link );

GSList *g_slist_reverse( GSList *list );

GSList *g_slist_nth( GSList *list, gint n );

GSList *g_slist_find( GSList *list, gpointer data );

GSList *g_slist_last( GSList *list );
 
gint g_slist_length( GSList *list );
 
void g_slist_foreach( GSList *list, GFunc func, gpointer user_data );

4、存储管理

gpointer g_malloc( gulong size );
这是 malloc() 函数的替代函数,不需要检查返回值,因为此函数已替你做这件事了。如果存储分配因任何原因失败,应用程序将被终止。
 
gpointer g_malloc0( gulong size );
和上一函数相同,但在返回指向所分配存储块的指针之前,将该存储块清 0。

gpointer g_realloc( gpointer mem, gulong   size );
重新分配由mem开始,大小为 size 字节的存储块。明显地,该存储块先前已被分配。

void g_free( gpointer mem );
释放分配的存储块。这很简单。如果 mem 为 NULL,则直接返回。

void g_mem_profile( void );
把用过的存储块的内容转储到一个文件中。但要这样做,需要将#define MEM_PROFILE加到文件 glib/gmem.c 的开始处,然后重新运行命令 make 和make install。

void g_mem_check( gpointer mem );
检查存储位置的有效性。需要将#define MEM_CHECK加到文件 glib/gmem.c 的开始处,然后重新运行命令 make 和 make install。
 
5、计时器

计时器函数可用于对操作计时(即查看操作所耗费的时间)。首先用 g_timer_new() 函数建立一个新计时器,然后用 g_timer_start() 函数启动计时,用g_timer_stop() 停止计时,用 g_timer_elapsed() 函数决定所耗的时间。

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 );

gdouble g_timer_elapsed( GTimer *timer, gulong *microseconds );


6、字符串处理

GLib 定义了一个叫做 GString 的新类型,该类型相似于标准 C 中的string,但可以自动增长。字符串数据以null结尾。该类型可以防止程序中的缓冲区溢出错误。这是一个非常重要的特性,因此我推荐使用 GString。GString 有一简单定义:
struct GString {
 gchar *str; /* 指向当前以'\0'结尾的字符串。 */
 gint len; /* 当前长度 */
};
 
如所预想的,有许多对一个 GString 型字符串的操作。
 
GString *g_string_new( gchar *init );
这个函数构造一个 GString 型字符串,它把 init指向的字符串值复制到 GString 型字符串中,返回一个指向它的指针。建一个初始为空的 GString 型字符串则传递一个 NULL 作为参数。

void g_string_free( GString *string, gint free_segment );
该函数释放给定的 GString 型字符串的存储空间。如果参数 free_segment 为TRUE,也释放其字符数据。

GString *g_string_assign( GString *lval, const gchar *rval );
该函数将 rval 中的字符复制到 lval 中,覆盖 lval 中以前的内容。注意为装下复制的字符串,lval 会变长,这是和标准的 strcpy() 数不一样的。

以下函数的功能是相当明显的(带有_c的版本接受一个字符而不是一个字符串):
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, ...);

void g_string_sprintfa ( GString *string, gchar *fmt, ... );


7、实用程序和错误处理函数

gchar *g_strdup( const gchar *str );
替代strdup函数。把原字符串内容复制到新分配的存储块中,返回指向它的指针。

gchar *g_strerror( gint errnum );
推荐使用此函数处理所有错误信息,它比 perror() 和其它类似函数更好,更具可移植性。此函数的输出通常为如下格式:
program name:function that failed:file or further description:strerror
 
这里有一个在我们的hello_world程序中调用此函数的示例:
g_print("hello_world:open:%s:%s\n", filename, g_strerror(errno));
void g_error( gchar *format, ... );

打印错误信息。格式同于 printf,但在错误信息前加上了"** ERROR **",并且退出程序。仅用在致命错误上。

void g_warning( gchar *format, ... );
和前一函数功能相同,只是错误信息前是 " ** WARNING ** ",且不退出程序。

void g_message( gchar *format, ... );
在传递的字符串前打印 "message:"

void g_print( gchar *format, ... );
替代 printf() 函数。
 
本章最后一个函数:
gchar *g_strsignal( gint signum );

对所给信号的号码打印出相应的信号名称,在通用信号处理函数中有用到。


使用glib库的程序都应该包含glib的头文件glib.h。

########################### glib基本类型定义 ##############################
整数类型:
gint8、guint8、gint16、guint16、gint32、guint32、gint64、guint64。
不是所有的平台都提供64位整型,如果一个平台有这些, glib会定义G_HAVE_GINT64。
类型gshort、glong、gint和short、long、int完全等价。

布尔类型:
gboolean:它可使代码更易读,因为普通C没有布尔类型。
gboolean可以取两个值:TRUE和FALSE。实际上FALSE定义为0,而TRUE定义为非零值。

字符型:
gchar和char完全一样,只是为了保持一致的命名。

浮点类型:
gfloat、gdouble和float、double完全等价。

指针类型:
gpointer对应于标准C的void *,但是比void *更方便。
指针gconstpointer对应于标准C的const void *(注意,将const void *定义为const gpointer是行不通的)

########################### glib的宏 ##############################
一些常用的宏列表
#include <glib.h>
TRUE
FALSE
NULL
MAX(a, b)
MIN(a, b)
ABS ( x )
CLAMP(x, low, high)

TRUE / FALSE / NULL就是1 / 0 / ( ( v o i d * ) 0 )。
MIN ( ) / MAX ( )返回更小或更大的参数。
ABS ( )返回绝对值。
CLAMP(x,low,high )若X在[low,high]范围内,则等于X;如果X小于low,则返回low;如果X大于high,则返回high。

有些宏只有g l i b拥有,例如在后面要介绍的gpointer-to-gint和gpointer-to-guint。
大多数glib的数据结构都设计成存储一个gpointer。如果想存储指针来动态分配对象,可以这样做。
在某些情况下,需要使用中间类型转换。
//////////////////////////////////////////////////////////////
gint my_int;
gpointer my_pointer;
my_int = 5;
my_pointer = GINT_TO_POINTER(my_int);
printf("We are storing %dn", GPOINTER_TO_INT(my_pointer));
//////////////////////////////////////////////////////////////

这些宏允许在一个指针中存储一个整数,但在一个整数中存储一个指针是不行的。
如果要实现的话,必须在一个长整型中存储指针。
宏列表:
在指针中存储整数的宏
#include <glib.h>
GINT_TO_POINTER ( p )
GPOINTER_TO_INT ( p )
GUINT_TO_POINTER ( p )
GPOINTER_TO_UINT ( p )

调试宏:
定义了G_DISABLE_CHECKS或G_DISABLE_ASSERT之后,编译时它们就会消失.
宏列表:
前提条件检查
#include <glib.h>
g_return_if_fail ( condition )
g_return_val_if_fail(condition, retval)

///////////////////////////////////////////////////////////////////////////////////
使用这些函数很简单,下面的例子是glib中哈希表的实现:
void g_hash_table_foreach (GHashTable *hash_table,GHFunc func,gpointer user_data) {
GHashNode *node;
gint i;
g_return_if_fail (hash_table != NULL);
g_return_if_fail (func != NULL);
for (i = 0; i < hash_table->size; i++)
   for (node = hash_table->nodes[i]; node; node = node->next)
  (* func) (node->key, node->value, user_data);
}
///////////////////////////////////////////////////////////////////////////////////

宏列表:
断言
#include <glib.h>
g_assert( condition )
g_assert_not_reached ( )
如果执行到这个语句,它会调用abort()退出程序并且(如果环境支持)转储一个可用于调试的core文件。

断言与前提条件检查的区别:
应该断言用来检查函数或库内部的一致性。
g_return_if_fail()确保传递到程序模块的公用接口的值是合法的。
如果断言失败,将返回一条信息,通常应该在包含断言的模块中查找错误;
如果g_return_if_fail()检查失败,通常要在调用这个模块的代码中查找错误。
//////////////////////////////////////////////////////////////////////
下面glib日历计算模块的代码说明了这种差别:
GDate * g_date_new_dmy (GDateDay day, GDateMonth m, GDateYear y) {
   GDate *d;
   g_return_val_if_fail (g_date_valid_dmy (day, m, y), NULL);
   d = g_new (GDate, 1);
   d->julian = FALSE;
   d->dmy = TRUE;
   d->month = m;
   d->day = day;
   d->year = y;
   g_assert (g_date_valid (d));
   return d;
}
//////////////////////////////////////////////////////////////////////
开始的预条件检查确保用户传递合理的年月日值;
结尾的断言确保glib构造一个健全的对象,输出健全的值。

断言函数g_assert_not_reached() 用来标识“不可能”的情况,通常用来检测不能处理的
所有可能枚举值的switch语句:
switch (val) {
case FOO_ONE:
   break ;
case FOO_TWO:
   break ;
default:
gint len;
} ;

用下面的函数创建新的GString变量:
GString *g_string_new( gchar *init );

这个函数创建一个GString,将字符串值init复制到GString中,返回一个指向它的指针。
如果init参数是NULL,创建一个空GString。

void g_string_free( GString *string,gint free_segment );
这个函数释放string所占据的内存。free_segment参数是一个布尔类型变量。
如果free_segment参数是TRUE,它还释放其中的字符数据。

GString *g_string_assign( GString *lval,const gchar *rval );
这个函数将字符从rval复制到lval,销毁lval的原有内容。
注意,如有必要, lval会被加长以容纳字符串的内容。

下面的函数的意义都是显而易见的。其中以_c结尾的函数接受一个字符,而不是字符串。
截取string字符串,生成一个长度为l e n的子串:
GString *g_string_truncate( GString *string,gint len );
将字符串val追加在string后面,返回一个新字符串:
GString *g_string_append( GString *string,gchar *val );
将字符c追加到string后面,返回一个新的字符串:
GString *g_string_append_c( GString *string,gchar c );
将字符串val插入到string前面,生成一个新字符串:
GString *g_string_prepend( GString *string,gchar *val );
将字符c插入到string前面,生成一个新字符串:
GString *g_string_prepend_c( GString *string,gchar c );
将一个格式化的字符串写到string中,类似于标准的sprintf函数:
void g_string_sprintf( GString *string,gchar *fmt,. . . ) ;
将一个格式化字符串追加到string后面,与上一个函数略有不同:
void g_string_sprintfa ( GString *string,gchar *fmt,... );

################################## 计时器函数 ##################################
创建一个新的计时器:
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 );
获取计时器流逝的时间:
gdouble g_timer_elapsed( GTimer *timer,gulong *microseconds );

################################## 错误处理函数 ##################################
gchar *g_strerror( gint errnum );
返回一条对应于给定错误代码的错误字符串信息,例如“ no such process”等。
使用g_strerror函数:
g_print("hello_world:open:%s:%sn", filename, g_strerror(errno));

void g_error( gchar *format, ... );
打印一条错误信息。
格式与printf函数类似,但是它在信息前面添加“ ** ERROR **: ”,然后退出程序。它只用于致命错误。

void g_warning( gchar *format, ... );
与上面的函数类似,在信息前面添加“ ** WARNING **:”,不退出应用程序。它可以用于不太严重的错误。

void g_message( gchar *format, ... );
在字符串前添加“message: ”,用于显示一条信息。

gchar *g_strsignal( gint signum );
打印给定信号号码的Linux系统信号的名称。在通用信号处理函数中很有用。

################################## 其他实用函数 ##################################
glib还提供了一系列实用函数,可以用于获取程序名称、当前目录、临时目录等。
这些函数都是在glib.h中定义的。
/* 返回应用程序的名称* /
gchar* g_get_prgname (void);
/* 设置应用程序的名称* /
void g_set_prgname (const gchar *prgname);
/* 返回当前用户的名称* /
gchar* g_get_user_name (void);
/* 返回用户的真实名称。该名称来自“passwd”文件。返回当前用户的主目录* /
gchar* g_get_real_name (void);
/* 返回当前使用的临时目录,它按环境变量TMPDIR、TMPandTEMP 的顺序查找。
如果上面的环境变量都没有定义,返回“ / t m p”* /
gchar* g_get_home_dir (void);
gchar* g_get_tmp_dir (void);
/* 返回当前目录。返回的字符串不再需要时应该用g_free ( ) 释放* /
gchar* g_get_current_dir (void);
/ *获得文件名的不带任何前导目录部分的名称。它返回一个指向给定文件名字符串的指针* /
gchar* g_basename (const gchar *file_name);
/* 返回文件名的目录部分。如果文件名不包含目录部分,返回“ .”。
 * 返回的字符串不再使用时应该用g_free() 函数释放* /
gchar* g_dirname (const gchar *file_name);
/* 如果给定的file_name是绝对文件名(包含从根目录开始的完整路径,比如/usr/local),返回TRUE * /
gboolean g_path_is_absolute (const gchar *file_name);
/* 返回一个指向文件名的根部标志(“/”)之后部分的指针。
 * 如果文件名file_name不是一个绝对路径,返回NULL * /
gchar* g_path_skip_root (gchar *file_name);
/ *指定一个在正常程序终止时要执行的函数* /
void g_atexit (GVoidFunc func);

上面介绍的只是glib库中的一小部分, glib的特性远远不止这些。如果想了解其它内容,参考glib.h文件。这里面的绝大多数函数都是简明易懂的。
另外,http://www.gtk.org上的glib文档也是极好的资源。

如果需要一些通用的函数但glib中还没有,考虑写一个glib风格的例程,将它贡献到glib库中!


本文总结自互联网,感谢原作者。