GObject Properties May 18, 2008
After creating a number of signals and functions on my own to handle my class’ fields, I reaised that GLib 1-uped me, and already has a frame work for that; properties. Properties are well exposed to the rest of the framework, can be elegantly handled using the g_object_set
and g_object_get
functions, and of course, emit signals whenever they are modified. This means you get signal creation free of cost. This was something I didn’t find well treated in the tutorial. There is a lot of boiler plate code that goes into enabling properties. An outline of the process (which is very well documented in the standard tutorial):
#define
a bunch of macros with a unique number for each property.- Register the property in the
_class_init
using theg_param_spec_ ()
function andgobject_class_install_property()
, with the aforementioned number. - Implement functions for the
_get_property
and_set_property
functions. This is done using a switch-case on theproperty_id
, matched the macros. You can either code how to get/set the property inline in each case statement, or call functions for them (depending on the complexity).
If it all boils down to just calling get/set functions anyway, you may question the whole point of properties. Some reasons to make you think otherwise (following the same theme as previous posts):
- A clean way of setting fields while constructing objects:
plot = g_object_new (
PLOTS_TYPE_WDP,
"probability", 0.42, // probability of success
"codename", "Polka-dotted Panther", // Something jazzy
"schedule", NULL, // Who needs timelines anyways?
NULL);
- A similar way of getting and setting properties:
g_object_set (obj,
"probabilty", 0.23, // Things are never as optimistic as you make them out to be
// the codename sounds cool enough
"schedule", &last_minute, // Procrastination != cool
NULL);
// _get puts the value of the fields into the variables
g_object_get (obj,
// To put on the list of "yet another plan that failed"
"codename", &codename,
NULL);
- Signal emission, via the “notify” signal:
// listen for whenever probability changes
sig_id = g_signal_connect (
plot,
"notify:probability",
(GCallback)back_to_the_drawing_board, // The function checks if probability = 0
NULL);
// Note, the callback has a special argument, the properties' specification:
back_to_the_drawing_board (PlotsPlot *plot, GParamSpec *param, gpointer user_data);
In an enlightening discussion with the davyd
on #gnome-hackers
, he told me how you can use these notify signals to elegantly connect up widgets to their models, thus really creating a MVC (Model-View-Controller) framework. Certain properties expose other useful snippets data like min/max value for the G_PARAM_SPEC_INT
property, which could be used on a spin-controller. Sadly, there is no ready-made function to link up a widget and a data ‘source’. I haven’t done it myself, so I can’t comment on how easy/hard it may be, but according to davyd
it’s simple, and largely boilerplate.
- Your objects are now introspectable (I honestly don’t understand the implications of this)
- Your objects can be easily language-binded
- You’ll be seeing lots of properties in all sorts of objects, for example GTK+ widgets. Might as well get used to it. People using your code will expect the same.