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 + -
显示快捷键?