gtk-gnome-intro.html
来自「linux下gnome编程」· HTML 代码 · 共 999 行 · 第 1/3 页
HTML
999 行
><TD><PRECLASS="PROGRAMLISTING">typedef void (*GLogFunc)(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data);guint g_log_set_handler(const gchar *log_domain, GLogLevelFlags log_levels, GLogFunc log_func, gpointer user_data); </PRE></TD></TR></TABLE><P> The GLogLevelFlags parameter is an enum of bit flags that define the character and specific channel of a logging message. The three you'll most likely use with logging handlers are G_LOG_LEVEL_MESSAGE, G_LOG_LEVEL_WARNING, and G_LOG_LEVEL_ERROR. Since they are bit flags, you can use a binary OR operator to combine more than one channel into a single handler. Listing 2.1 shows how to send g_message( ) and g_warning( ) to a log file, myapp.log. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 2.1 Overriding a Logging Handlervoid LogToFile (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data){ FILE *logfile = fopen ("myapp.log", "a"); if (logfile == NULL) { /* Fall back to console output if unable to open file */ printf ("Rerouted to console: %s\n", message); return; } fprintf (logfile, "%s\n", message); fclose (logfile);}int main(int argc, char *argv[]){ ... /* Send g_message( ) and g_warning( ) to the file */ g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING, LogToFile, NULL); ...} </PRE></TD></TR></TABLE><P> The g_print( ) function has its own set of override functions, which behave pretty much the same. The g_set_print_handler( ) function returns the old g_print( ) handler, in case you want to restore it later. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef void (*GPrintFunc)(const gchar *string);GPrintFunc g_set_print_handler(GPrintFunc func); </PRE></TD></TR></TABLE></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN77">Containers</A></H2><P> GLib has many valuable container types, including linked lists, strings, arrays, and binary trees, with a wide range of functions to manipulate them all. We don't have nearly enough space to go into them in any depth; such a pursuit could easily take up an entire chapter. A quick tour will suffice to give you a feel for what GLib has to offer. You can peruse the GLib documentation to find out in greater detail how to use these functions. </P><P> The simplest container is a string. GLib offers two types of string support. The first category of string functions consists of wrapper functions around common UNIX-style string functions that may or may not exist on all plat- forms, such as g_snprintf( ), g_strcasecmp( ), g_strdup( ), and g_strconcat( ). All of these functions act directly on gchar* strings. </P><P> The string functions of the other category perform actions on GLib's abstract string wrapper, GString: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">typedef struct _GString GString;struct _GString{ gchar *str; gint len;}; </PRE></TD></TR></TABLE><P> All of these functions have the form g_string_*, such as g_string_new( ), g_string_sprintf( ), g_string_append( ), g_string_free( ), and so on. You can use the g_string_* functions to operate opaquely on a GString structure (the preferred method), or you can access the structure members directly and use the normal UNIX-flavor string functions, although you should be careful to keep the len field in sync with the str field if you make changes to it. </P><P> GLib has three types of array containers: GArray, GByteArray, and GPtrArray. Each array expands and shrinks automatically as you add and remove elements, thus insulating you from the boring and potentially dangerous responsibility of maintaining your arrays. As with most GLib containers, you create them with a _new( ) function and release them with a _free( ) function. Each array also has various append, prepend, add, remove, and accessor functions. The array containers can grow and shrink automatically as you add and remove elements. </P><P> GArray, the most generic array, stores arbitrary, uniformly sized elements. When you create the GArray, you must specify the size the elements will be. When you add new elements, GLib copies them directly into the GArray, after which you can delete the original copies. GByteArray is a special case of GArray in which the size of each element is hard-coded to a single byte. GPtrArray is another special case of GArray in which each element is a pointer that (theoretically) points to a chunk of data outside the array. When you free a GArray or GByteArray, GLib automatically cleans up all the data inside the ar- ray. Conversely, when you free a GPtrArray, GLib always cleans up the memory for the pointers themselves, but may or may not clean up the external (pointed to) data; the g_ptr_array_free( ) function contains a Boolean parameter to specify whether or not you want to also free up the external data. </P><P> GLib comes with two types of linked-list containers: singly linked (GSList) and doubly linked (GList). The only difference between the two is the number of directions in which you can iterate over the elements (see Figure 2.1). A singly linked list allows one direction: forward only. A doubly linked list allows both directions: forward and backward. The concept of a linked list is very simple. Each element of a linked list contains a pointer to the data, plus a pointer to the next (or previous) element. All elements are connected together in a consecutive chain. </P><DIVCLASS="FIGURE"><ANAME="AEN87"></A><P><B>Figure 2-1. Singly and Doubly Linked Lists</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/2f1.png"></IMG></P></DIV></DIV><P> Because each element knows about only its immediate neighbors, you can easily insert elements at the beginning, middle, or end of the list, without moving all the others around. This is much more efficient than insertion into an array, in which case you must displace every element between the new element and the end of the array. On the other hand, random access is more expensive with linked lists. If you want to find the thirteenth element, for example, you must pass through each of the first 12 elements in the chain to get to the one you want. Since arrays are laid out in contiguous memory, you can calculate the exact position of the thirteenth element with a little pointer math and go right to it. Which type of container you use should depend on how you expect to manipulate the data. </P><P> A singly linked list element looks like this: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">struct GSList{ gpointer data; GSList *next;}; </PRE></TD></TR></TABLE><P> A doubly linked list is almost identical. The only difference is a second list pointer, to the previous element. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">struct GList{ gpointer data; GList *next; GList *prev; }; </PRE></TD></TR></TABLE><P> The data field is a generic void* pointer, so you'll need to cast it to the proper data type before using it. You can iterate through the elements by cycling through the next field. Creating a linked list with GLib is simple. You just start adding elements to a NULL list pointer; GLib will allocate new elements for you and load your data into them as it goes. </P><P> Both types of linked lists have the same basic API. Singly linked list functions have the prefix g_slist_; doubly linked lists have the prefix g_list_. Otherwise, the two function sets look and behave the same (although for obvi- ous reasons GSList is lacking the g_list_previous( ) function of GList). </P><P> Another common type of data container is the hash table (see Figure 2.2). Hash tables are good for storing nonsequential data and accessing it randomly. Each piece of data is associated with a key, which is usually a string or an inte- ger that uniquely identifies that piece of data. For example, you might use an employee's name (or ID number) as a key to looking up the data structure of his or her employee information. Each key can refer to only one data item, so if you save two pieces of data to the same key, the second item overwrites the first. The number of keys always exactly matches the number of data items stored in the hash table. </P><DIVCLASS="FIGURE"><ANAME="AEN100"></A><P><B>Figure 2-2. Structure of a Hash Table</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/2f2.png"></IMG></P></DIV></DIV><P> To keep things efficient, the keys are hashed, or converted, into an integer value with the GHashFunc algorithm, which is then used for lookups. This hash value may or may not be unique among all possible keys. When collisions occur and more than one key results in the same hash value, GLib's GHashTable will form a bucket, or a linked list of data items that correspond to the same hash value. Such is the case in Figure 2.2, in which keys 1 and 3 share the same hash value and are thus stored in the same bucket. To figure out which value in the bucket refers to which key, you must supply a GCompareFunc callback to test for equality between two keys. In Figure 2.2, when looking up key 3, GLib will run the GCompareFunc on key 3 versus each key in bucket A-that is, GCompareFunc(key3, key1), then GCompareFunc(key3, key3)-until it finds a match. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRE
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?