I Am a GObject

18 05 2008

This past week, I’ve been up close and personal with GObjects, deciding to finally learn how to use them. Till now, most of my hacking has been with Gtk+, and that too largely in Python, which is, well…, child’s play. Luckily, I had a lot of patience to work out the boiler plated code, and figure out it’s various idiosyncrasies, enough so to appreciate what it’s trying to do.

Before I say anything further, kudos to Mathieu Lacage’s for his helpful tutorial, which has been included in the official GNOME docs. It very clearly explains the motivation behind the whole GObject concept, which, to be fully honest is required if you want to make sense of it. He also did well in introducing the naming conventions used by GNOME.

GObjects really gave me an insight into C++ and other OOP-ly languages, and I decided to come up with a mapping of C++ to GObject terms, that the Brain (of Pinky and the Brain fame) might find handy. Hopefully, it will appeal to non-fictional characters as well. (Note: I’ve excluded the constructor and destructor functions which are implemented in the boilerplate _constructor and _finalize functions).

If you’ve ever used GObjects, you’d see a load of boilerplate functions. I felt a bit uncomfortable about the various _init functions even after reading the docs, so I stepped through with a debugger to see what happens where. Here’s another diagram.

A few notes:

  • I’ve found that putting the signal code into the _class_init function seems more logical, and well… works, however, in the tutorial, Mathieu puts these in the constructor.
  • There’s an interesting loop that occurs between the _constructor and the _instance_init functions. The tutorial explains:

    Finally, at one point or another, g_object_constructor is invoked by the last constructor in the chain. This function allocates the object’s instance’ buffer through g_type_create_instance  which means that the instance_init function is invoked at this point if one was registered. After instance_init returns, the object is fully initialized and should be ready to answer any user-request. When g_type_create_instance  returns, g_object_constructor sets the construction properties (i.e. the properties which were given to g_object_new) and returns to the user’s constructor which is then allowed to do useful instance initialization…

  • Despite this, I can’t find a use for the _instance_init function. I’d be delighted to hear an explanation.

The diagrams were made using Dia. I’d upload them if WordPress would allow me to.



6 responses

18 05 2008

the instance initialization function sets up the basic state of the instance, as it is without any constructor property set.

the constructor can take those properties into account to update the state.

since 2.12, there’s also the ::constructed virtual function which gets called after the instance has been initialized and constructed.

and while there are many adjectives I’d use for the gobject tutorial – ‘excellent’ is not one of them.

18 05 2008

oh, and I saw from your diagrams that you’re using the dumb suggestion from the gobject tutorial of storing the signal ids into the class structure.

don’t do it

it’s broken, it exposes data that’s not even meant to escape your source file and that might change at each compilation or at each execution.

if you want to emit a signal from a subclass, use g_signal_emit_by_name().

and while there are many adjectives I’d use for the gobject tutorial – ‘excellent’ is not one of them.

I really mean this.

18 05 2008

@Emmanuele: I get your point, but there really aren’t any other resources out there. The tutorial was obscure at a few plaec. but I thought I had gotten some understanding of GObjects from it. Perhaps I am absolutely wrong.

About the _instance_init function, what purpose does it serve that a constructor can not handle?

About the signal emission, what do you suggest as the recommended implementation?

18 05 2008

I know – unfortunately, you’re right: the tutorial is the only document available. I started at least a discussion on gtk-devel-list about fixing it, and I plan to have something ready for the next stable release.

as for your questions:

– instance init is not replacing a ::constructor; as well as ::constructor is not replacing the instance init; most of the classes don’t need the complexity of the ::constructor override (chain up, create the instance, cast it, return the GObject), so the instance init will do. also, if you have constructor-only properties, the instance init will create the base initialization to be modified by those properties. it’s just cleaner.

– as for signal emission: just create a simple array of unsigned integers and use it to store the signal ids, like:

enum {

static guint instance_signals[LAST_SIGNAL] = { 0, };

instance_signals[FOO] = g_signal_new (…);
instance_signals[BAR] = g_signal_new (…);

g_signal_emit (instance, instance_signals[FOO], 0);

it’s cleaner – because these signal ids will never be visible outside your source code, and your class structure will just hold function pointers for the class signal handlers (you can even avoid that by using internal functions). the goal is to keep the instance and class structures as opaque as possible because changing them will break API and ABI. in gtk+ we’re trying extra-hard to remove all these public member so that we can avoid breaking API when removing unneeded stuff.

19 05 2008

@ Emmanuele: Ok thanks for explaining that. Can I say that process of storing signal ids is absolutely not required, considering you can use g_signal_lookup to get signal_ids?

And in your revised tutorials, could you cover subclassing and signal accumulators?

19 05 2008

a lookup might be expensive (it isn’t, but for the sake of argument let’s assume it is), so storing the ids is perfectly fine – they are unsigned integers, anyway. 🙂

as for the revised tutorial: subclassing is definitely needed; signal accumulators might be an interesting chapter – even though I’d prefer to have documentation in the API reference page of the GSignal API.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: