2.2 Compiling Hello World
To compile use:
|
This uses the program gtk-config, which comes with GTK. This program "knows" what compiler switches are needed to compile programs that use GTK. gtk-config --cflags will output a list of include directories for the compiler to look in, and gtk-config --libs will output the list of libraries for the compiler to link with and the directories to find them in. In the above example they could have been combined into a single instance, such as `gtk-config --cflags --libs`.
Note that the type of single quote used in the compile command above is significant.
The libraries that are usually linked in are:
The GTK library (-lgtk), the widget library, based on top of GDK.
The GDK library (-lgdk), the Xlib wrapper.
The gmodule library (-lgmodule), which is used to load run time extensions.
The GLib library (-lglib), containing miscellaneous functions; only g_print() is used in this particular example. GTK is built on top of glib so you will always require this library. See the section on GLib for details.
The Xlib library (-lX11) which is used by GDK.
The Xext library (-lXext). This contains code for shared memory pixmaps and other X extensions.
The math library (-lm). This is used by GTK for various purposes.
2.3 Theory of Signals and Callbacks
Before we look in detail at helloworld, we'll discuss signals and callbacks. GTK is an event driven toolkit, which means it will sleep in gtk_main until an event occurs and control is passed to the appropriate function.
This passing of control is done using the idea of "signals". (Note that these signals are not the same as the Unix system signals, and are not implemented using them, although the terminology is almost identical.) When an event occurs, such as the press of a mouse button, the appropriate signal will be "emitted" by the widget that was pressed. This is how GTK does most of its useful work. There are signals that all widgets inherit, such as "destroy", and there are signals that are widget specific, such as "toggled" on a toggle button.
To make a button perform an action, we set up a signal handler to catch these signals and call the appropriate function. This is done by using a function such as:
|
where the first argument is the widget which will be emitting the signal, and the second the name of the signal you wish to catch. The third is the function you wish to be called when it is caught, and the fourth, the data you wish to have passed to this function.
The function specified in the third argument is called a "callback function", and should generally be of the form
|
where the first argument will be a pointer to the widget that emitted the signal, and the second a pointer to the data given as the last argument to the gtk_signal_connect() function as shown above.
Note that the above form for a signal callback function declaration is only a general guide, as some widget specific signals generate different calling parameters. For example, the CList "select_row" signal provides both row and column parameters.
Another call used in the helloworld example, is:
|
gtk_signal_connect_object() is the same as gtk_signal_connect() except that the callback function only uses one argument, a pointer to a GTK object. So when using this function to connect signals, the callback should be of the form
|
where the object is usually a widget. We usually don't setup callbacks for gtk_signal_connect_object however. They are usually used to call a GTK function that accepts a single widget or object as an argument, as is the case in our helloworld example.
The purpose of having two functions to connect signals is simply to allow the callbacks to have a different number of arguments. Many functions in the GTK library accept only a single GtkWidget pointer as an argument, so you want to use the gtk_signal_connect_object() for these, whereas for your functions, you may need to have additional data supplied to the callbacks.