Convenience! GLib for lists, sets, maps, and strings
GLib is a versatile utility library used in many applications and frameworks, especially those in the GNOME ecosystem. It provides data structures and utilities for C programming. Here's a guide on how to use some of its core features like ArrayLists, Sets, HashMaps, and Strings, along with installation and compilation instructions for Ubuntu.
Installing GLib in Ubuntu
Update Package Lists:
sudo apt update
Install GLib:
sudo apt install libglib2.0-dev
Compiling Code with GLib
To compile a program that uses GLib, use gcc
with the pkg-config
utility:
gcc `pkg-config --cflags --libs glib-2.0` -o your_program your_program.c
Replace your_program.c
with the name of your C source file, and your_program
with the desired name of the compiled executable.
Sample Code and Explanation
1. ArrayLists (GArray)
GArray is a resizable array which can hold any data type. Here's an example of using it with integers:
#include <glib.h>
int main() {
GArray *array = g_array_new(FALSE, FALSE, sizeof(int));
int num = 15;
// Adding elements
g_array_append_val(array, num);
// Accessing elements
num = g_array_index(array, int, 0);
// Removing an element
g_array_remove_index(array, 0);
// Free the array
g_array_free(array, TRUE);
return 0;
}
Including GLib
#include <glib.h>
This line includes the GLib header file, which contains the necessary declarations for using the GLib library in your program.
main Function
int main() {
This line starts the definition of the main
function, which is the entry point of a C program.
Creating a GArray
GArray *array = g_array_new(FALSE, FALSE, sizeof(int));
g_array_new
: This function creates a newGArray
.The first argument (
FALSE
) indicates that the array should not have zero-terminated elements. This is often set toTRUE
for arrays of characters (strings), but for an integer array,FALSE
is appropriate.The second argument (
FALSE
) decides whether the array elements should be cleared to 0 when they are allocated. For simple data types likeint
, this is typically not necessary.The third argument (
sizeof(int)
) specifies the size of each element in the array. In this case, we are storing integers, so the size issizeof(int)
.
Adding an Element to the Array
int num = 15;
g_array_append_val(array, num);
First, an integer
num
is initialized to 15.g_array_append_val
: This macro appends the value ofnum
to the end of the array. It's a convenient way to add elements to aGArray
.
Accessing Elements
num = g_array_index(array, int, 0);
g_array_index
: This macro is used for accessing elements of the array.It takes three arguments: the array, the type of the elements (
int
in this case), and the index of the element to access (0 here, which is the first element).
Removing an Element
g_array_remove_index(array, 0);
This function removes an element from the array.
The first argument is the array, and the second argument is the index of the element to remove. Here, it removes the element at index 0.
Freeing the Array
g_array_free(array, TRUE);
g_array_free
: This function is used to free the memory allocated for the array.The first argument is the array to be freed.
The second argument (
TRUE
) decides whether to free the actual element data. If set toTRUE
, it frees the memory allocated for the elements as well. If your array holds pointers to dynamically allocated data, you might need to manually free those before callingg_array_free
.
2. Sets (GHashSet)
GHashSet provides a way to store unique elements. Here's how you can use it:
#include <glib.h>
int main() {
GHashTable *set = g_hash_table_new(g_direct_hash, g_direct_equal);
// Adding elements
g_hash_table_add(set, GINT_TO_POINTER(1));
// Checking if an element is in the set
gboolean is_present = g_hash_table_contains(set, GINT_TO_POINTER(1));
// Removing an element
g_hash_table_remove(set, GINT_TO_POINTER(1));
// Free the set
g_hash_table_destroy(set);
return 0;
}
The provided code snippet demonstrates the usage of GHashTable
in GLib as a set. GHashTable
is a versatile hash table structure that can be used to implement various data structures, including sets and maps. In this example, it's used as a set to store unique elements. Let's break down the code:
Creating a GHashTable
GHashTable *set = g_hash_table_new(g_direct_hash, g_direct_equal);
g_hash_table_new
: This function creates a newGHashTable
.g_direct_hash
: A function pointer to a hashing function.g_direct_hash
is suitable for hashing pointers or integer values directly. It basically returns the key as its own hash.g_direct_equal
: A function pointer to a key equality function.g_direct_equal
compares pointers for equality, which is appropriate when using the hash table as a set of integers.
Adding Elements
g_hash_table_add(set, GINT_TO_POINTER(1));
g_hash_table_add
: This function adds a unique element to the set. If the element already exists in the set, the function does nothing.GINT_TO_POINTER(1)
: This macro converts an integer to a pointer. In C, hash tables cannot directly handle integers as keys or values since they work with pointers. This is a common technique to store integers in a data structure that expects pointers.
Checking if an Element is in the Set
gboolean is_present = g_hash_table_contains(set, GINT_TO_POINTER(1));
g_hash_table_contains
: This function checks whether the set contains a specific element.GINT_TO_POINTER(1)
: Again, the integer1
is converted to a pointer for the check.The result (TRUE or FALSE) is stored in the
gboolean
variableis_present
.
Removing an Element
g_hash_table_remove(set, GINT_TO_POINTER(1));
g_hash_table_remove
: This function removes an element from the set.The element to remove is specified by
GINT_TO_POINTER(1)
, which is the pointer representation of the integer1
.
Freeing the Set
g_hash_table_destroy(set);
g_hash_table_destroy
: This function releases all memory used by theGHashTable
.It not only frees the memory used by the hash table structure itself but also the memory for the elements stored in it. Since in this case, the elements are simple integer pointers (not dynamically allocated memory), there's no need for additional cleanup.
3. HashMaps (GHashTable)
GHashTable maps keys to values. This is a small example of using it:
#include <glib.h>
int main() {
GHashTable *hash = g_hash_table_new(g_str_hash, g_str_equal);
// Inserting key-value pairs
g_hash_table_insert(hash, "key1", "value1");
// Accessing value by key
char *value = g_hash_table_lookup(hash, "key1");
// Removing a key-value pair
g_hash_table_remove(hash, "key1");
// Free the hash table
g_hash_table_destroy(hash);
return 0;
}
Sure, let's go through this code snippet, which demonstrates the use of GHashTable
as a map in GLib. A hash table is a data structure that maps keys to values, providing efficient lookup, insertion, and deletion. In GLib, GHashTable
is a generic implementation of such a hash table. The code snippet uses strings as keys and values, which is a common use case.
Creating a GHashTable
GHashTable *hash = g_hash_table_new(g_str_hash, g_str_equal);
g_hash_table_new
: This function creates a newGHashTable
.g_str_hash
: A function pointer to a hashing function for strings. It calculates a hash value for a given string key. This is important for efficiently storing and retrieving data based on string keys.g_str_equal
: A function pointer to a key comparison function for strings. It determines how to compare two string keys for equality, which is crucial for operations like lookup and removal.
Inserting Key-Value Pairs
g_hash_table_insert(hash, "key1", "value1");
g_hash_table_insert
: This function inserts a new key-value pair into the hash table."key1"
: The string used as the key."value1"
: The string used as the value associated with"key1"
.Note: In this particular usage, the keys and values are string literals. In a more dynamic scenario, you might use dynamically allocated strings or other types of data.
Accessing Value by Key
char *value = g_hash_table_lookup(hash, "key1");
g_hash_table_lookup
: This function is used to find the value associated with a given key in the hash table."key1"
: The key for which the value is to be retrieved.The return value is a pointer to the value associated with the key. If the key is not found in the hash table, the function returns
NULL
.
Removing a Key-Value Pair
g_hash_table_remove(hash, "key1");
g_hash_table_remove
: This function removes a key-value pair from the hash table."key1"
: The key of the key-value pair to be removed.When a key-value pair is removed, both the key and the value are removed from the table. If you have dynamically allocated memory for keys or values, you should free it before removing them from the hash table.
Freeing the Hash Table
g_hash_table_destroy(hash);
g_hash_table_destroy
: This function releases all the memory used by theGHashTable
.It frees the memory used by the hash table structure. If the hash table contains dynamically allocated memory as keys or values, you must free them using a custom destroy function or manually free them before calling this function.
4. Strings (GString)
GString is a mutable string utility in GLib:
#include <glib.h>
int main() {
GString *str = g_string_new("Hello");
// Appending to a string
g_string_append(str, " World");
// Accessing the string's value
printf("%s\n", str->str);
// Replacing part of the string
g_string_replace(str, "World", "GLib");
// Free the string
g_string_free(str, TRUE);
return 0;
}
This code snippet demonstrates the use of GString
, a dynamic string utility provided by GLib. GString
is used for string manipulation, offering more flexibility than standard C strings. Let's break down the code:
Creating a GString
GString *str = g_string_new("Hello");
g_string_new
: This function creates a newGString
and initializes it with the given string."Hello"
: The initial value of theGString
.str
: A pointer to theGString
object.
Appending to a String
g_string_append(str, " World");
g_string_append
: This function appends a string to the end of theGString
." World"
: The string to be appended.After this operation,
str
will contain"Hello World"
.
Accessing the String's Value
printf("%s\n", str->str);
str->str
: This is how you access the actual C string (char *
) contained within theGString
object.GString
maintains a null-terminated C string for compatibility.The
printf
function is then used to print the current value of theGString
, which at this point is"Hello World"
.
Replacing Part of the String
g_string_replace(str, "World", "GLib");
g_string_replace
: This function is not a standard GLib function. Typically,g_string_replace
would be a custom function or part of an extension to GLib. Assuming it replaces all occurrences of a substring with another substring within theGString
.The code intends to replace
"World"
with"GLib"
in theGString
. However, without the implementation details ofg_string_replace
, we can't be sure how it behaves. If it works as expected, theGString
str
would then contain"Hello GLib"
.
Freeing the String
g_string_free(str, TRUE);
g_string_free
: This function is used to free the memory allocated for theGString
.str
: TheGString
to be freed.The
TRUE
argument indicates that the function should also free the character data (str->str
). If set toFALSE
, the function would only free theGString
wrapper, and you would need to freestr->str
manually.
Subscribe to my newsletter
Read articles from Jyotiprakash Mishra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jyotiprakash Mishra
Jyotiprakash Mishra
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class. At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out. In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.