GLib

GLib is a lower-level library that provides many useful definitions and functions, portable across different Architectures and Operating Systems:

  • Definitions for basic types and their limits, standard macros, type conversions, byte order.
  • Data structures and their related operations
  • Memory allocation
  • Warnings and assertions and message logging
  • Thread abstraction
  • Event Loop
  • Dynamic Loading of Modules

Links:

Basic Types

All the GLib basic types are included with the main header:

#include <glib.h>

GLib Type Corresponding Type in C
gchar char
guchar 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

Memory Management

The advantage of these functions over those in the standard C library is the built-in error handling. If a problem occurs during runtime, g_error() can step in to examine it.

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)

It is also provided a useful macro to allocate a desired number of data structures:

g_new(struct_type, n_structs)

C library

my_data = (dummy_data_type*) malloc(sizeof(dummy_data_type) * DATA_LENGTH);
if (my_data == NULL) {
    fprintf(stderr, "Couldn't allocate memory\n");
    exit(EXIT_FAILURE); // Should be called a system wide error handling routine.
}

GLib library

my_data = g_new(dummy_data_type, DATA_LENGTH);

Strings

GLib has utility functions to handle two types of strings:

  • Classical C Strings: gchar*
  • GLib string type: GStrings

gchar*

gchar strings can be passed as argument to all the string.h functions. Additionally, GLib provide the following functions:

GString

GString is a data type containing a pointer to the memory area containing the string chars, the length of the string and the length of the area of memory allocated for the string:

typedef struct _GString	  GString;
struct _GString {
  gchar  *str;
  gsize len;    
  gsize allocated_len;
};
GLib provides the following functions:

Message Logging

GLib uses four runtime error logging functions, in order of the priority levels:

Functions Level Meaning
g_message() G_LOG_LEVEL_MESSAGE for informative messages indicating normal runtime behavior
g_warning() G_LOG_LEVEL_WARNING for warnings or problems that won't cause errant operation (at least not yet)
g_critical() G_LOG_LEVEL_CRITICAL for warnings that likely are going to matter
g_error() for fatal errors; calling this function terminates your program

This utilities take parameters like printf() (a format string followed by a list of substitution parameters). There's no need to put a '\n' at the end of the format, though.

To add a signature (compile time) of the application to the log messages, it has to be used the G_LOG_DOMAIN macro.

#undef  G_LOG_DOMAIN
#define G_LOG_DOMAIN   "GLibTest"
[...]
g_message("Info message");
g_warning("Warning message");
g_critical("Critical message");
g_error("Error message");

GLibTest-Message: Info message

(process:18977): GLibTest-WARNING **: Warning message

(process:18977): GLibTest-CRITICAL **: Critical message

GLibTest-ERROR **: Error message
aborting...

In the default configuration, g_error is fatal. The function g_log_set_always_fatal can set other logging level as fatal, ie to set all warnings and critical messages as fatal:

g_log_set_always_fatal(G_LOG_LEVEL_WARNING|G_LOG_LEVEL_CRITICAL)

To facilitate an uniform logging through all the library there are also two wrapper functions to the classical print functions:

g_print()
g_printerr()

All these functions have ways to set different handlers.

g_log_set_handler()
g_set_print_handler()
g_set_printerr_handler()

The prototype of a log handler function is:

void (*GLogFunc)(const gchar    *log_domain,
                 GLogLevelFlags log_level,
                 const gchar    *message,
                 gpointer       user_data);

Timer

The Gtimer is nothing more than a stopwatch that is as accurate as your system clock. Here is a demonstration:

#include <glib.h> 
#define DURATION 200000 
 
int main(int argc, char **argv) { 
    GTimer *clock = NULL; 
    gint i; 
    gdouble elapsed_time; 
    gulong us;  /* microseconds */ 
 
    clock = g_timer_new(); 
    g_timer_start(clock); 
    g_print("Timer started.\n"); 
 
    g_print("Loop started.. "); 
    /* wasting CPU time like this is only allowed in programming examples */ 
    for (i = 0; i < DURATION; i++) { ; } 
 
    g_print("and finished.\n"); 
    g_timer_stop(clock); 
    g_print("Timer stopped.\n"); 
 
    elapsed_time = g_timer_elapsed(clock, &us); 
    g_print("Elapsed: %g s\n", elapsed_time); 
    g_print("         %ld us\n", us); 
 
    g_timer_destroy(clock); 
 
    return 0; 
}

Event Loop

Main Loop with context

GMainContext* context = NULL;
GMainLoop*    loop    = NULL;
 
context = g_main_context_new();
loop = g_main_loop_new(context, FALSE);
 
timeout_add_to_context(1000, periodic_one, NULL, context);
 
g_main_loop_run(loop);

Timeout on a generic context

guint timeout_add_to_context(guint interval, GSourceFunc func, gpointer data, GMainContext *context) {
    GSource *source;
    guint id;
 
    g_return_val_if_fail(func != NULL, 0);
 
    source = g_timeout_source_new(interval);
    g_source_set_callback(source, func, data, NULL);
    id = g_source_attach(source, context);
    g_source_unref(source);
 
    return id;		
}

Threads

Thread init

GThread *thread = NULL;
GError  *err    = NULL;
 
g_thread_init(NULL);
 
thread = g_thread_create(thread, NULL, TRUE, &err);

Mutex

static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
 
g_static_mutex_lock(&mutex);
/* ... */ 
g_static_mutex_unlock(&mutex);

IO Channels

Add a watch to a file descriptor

GIOChannel* channel;
channel = g_io_channel_unix_new(file_descriptor);
io_add_watch_to_context(channel, (G_IO_IN|G_IO_IN), io_handler, data);

Watch on a generic context

guint io_add_watch_to_context(GIOChannel *channel, GIOCondition condition, GSourceFunc func, gpointer data, GMainContext *context) {
    GSource *source;
    guint id;
 
    g_return_val_if_fail(channel != NULL, 0);
    g_return_val_if_fail(func    != NULL, 0);
 
    source = g_io_create_watch(channel, condition);
    g_source_set_callback(source, func, data, NULL);
    id = g_source_attach(source, context);
    g_source_unref(source);
 
    return id;
}

Makefile

# C Compiler settings
CC=gcc
CC_FLAGS=-O2 -g -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations 

# Header files needed by the compiler
CC_INCLUDES=-I.             \
-pthread                    \
-I/usr/include/glib-2.0     \
-I/usr/lib/glib-2.0/include

# Libraries needed by the linker 
LD_LIBS=-pthread    \
-L/usr/lib          \
-Wl,-rpath,/usr/lib \
-lglib-2.0 

# Project Files
MODULES=./main.o

# Target executable file
TARGET=exec

all: $(TARGET)

clean:
	rm -f $(TARGET) $(MODULES)

$(TARGET): $(MODULES)
	$(CC) $(CC_INCLUDES) $(CC_FLAGS) -o $@ $(MODULES) $(LD_LIBS)
	
%.o: %.c
	$(CC) $(CC_INCLUDES) $(CC_FLAGS) -c -o $*.o  $<

,
c/glib.txt · Last modified: 2010/08/12 by emilmont
CC Attribution-Noncommercial-Share Alike 3.0 Unported
Valid CSS Driven by DokuWiki Recent changes RSS feed Valid XHTML 1.0