I've just been working with GTK+, a GUI toolkit for C/Linux - but ported to pretty much everything. Initial impressions are quite good, although I am starting to miss Qt/Creator Anyhow, I hit the age-old problem quite quickly. The GUI thread just isn''t enough. To start with, I just slapped in a ''normal'' thread (pthread_t) but when the time came to update the GUI, things started to go pete tong. Here is how I sorted it;
GTK+ is described as ''thread aware'' rather than ''thread safe'' so you need to be a bit careful, although after a little investigation it gets very simple.
Firstly, let GLib/GTK know that it may need to share (these should be done FIRST and in this order before any other GLib code gets run);
1 2 |
g_thread_init(NULL); gdk_threads_init(); |
Then you can start a thread;
1 2 |
GError *gError = NULL; g_thread_create(my_thread, pMyData, FALSE, &Error); |
The prototype of the thread function you want to call should look something like this;
1 |
void *my_thread(void *ptr);
|
Finally all critical code should be wrapped in;
1 |
gdk_threads_enter();
|
and
1 |
gdk_threads_leave();
|
INCLUDING gtk_main();
These functions are basically mutex macros which stop two threads accessing the same data at the same time.
Compile in the same way as any other GTK+ program, but ensure the following is added to the compiler options;
1 |
-lgthread-2.0
|
Here is a very simple example for clarification;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include <gtk/gtk.h> / Label that we will change the text of GtkWidget *label; // The thread. void *my_thread(void *pData) { gdk_threads_enter(); gtk_label_set_text(GTK_LABEL(label), "Not My Label"); gdk_threads_leave(); return 0; } int main(int argc, char *argv[]) { // Thread safe g_thread_init(NULL); gdk_threads_init(); // Load GUI. gtk_init (&argc, &argv); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // Simple label label = gtk_label_new("My Label"); gtk_container_add(GTK_CONTAINER(window), label); gtk_widget_show(label); gtk_widget_show(window); // Load the thread. GError *error = NULL; void *pData = 0x00; if (!g_thread_create(my_thread, pData, FALSE, &error)) { g_printerr ("Failed to create thread: %sn", error->message); return 1; } // Run window. gdk_threads_enter(); gtk_main(); gdk_threads_leave(); return 0; } |
It can be compiled using the following;
1 |
gcc -Wall -g shoal_test.c `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0` -lgthread-2.0
|
Its as simple as that. I hope it helps someone!





