Wednesday, July 22, 2009

The Missing GObject Tutorial Sample

Well, perhaps not exactly, but still -- I think it should work.

I've recently started poking around the GObject library, which is part of GLib. GObject is a C library aimed at providing OOP programmability that easily integrates with (usually) dynamic third-party languages. Basically, it allows you to write "glue" code between $your_dynamic_language and the GObject library just once, and then hook into any libraries created with GObject without writing further glue.

A good, detailed tutorial is available here, which I've been working through. After getting the gist of something, I get itchy for some sample code to play around with. So I Googled and found this how-to. An older version of the documentation mentioned some sample code that I was never able to find.

After giving up on that, I decided that I should be able to use the tutorial to scrap together my own sample. The tutorial was pretty detailed, after all, and apparently referenced a sample that did (or does) exist somewhere. So that's what I did. I've created a fully functioning sample based more-or-less on the tutorial mentioned above. The code is below, with comments.

I have compiled this on my Ubuntu 8.10 and 9.04 machines using the following command:

gcc `pkg-config --libs gtk+-2.0` `pkg-config --cflags gtk+-2.0` maman-bar.c


* Copyright/Licensing information.
* Reference:

/* inclusion guard */
#ifndef __MAMAN_BAR_H__
#define __MAMAN_BAR_H__

#include <glib-object.h>

* Potentially, include other headers on which this header depends.

* Type macros.
#define MAMAN_TYPE_BAR (maman_bar_get_type ())
#define MAMAN_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MAMAN_TYPE_BAR, MamanBarClass))

typedef struct _MamanBar MamanBar;
typedef struct _MamanBarClass MamanBarClass;

* Private instance fields
* Uses the Pimpl method:
typedef struct _MamanBarPrivate MamanBarPrivate;

/* object */
struct _MamanBar
GObject parent_instance;

/* public */
int public_int;

/*< private >*/
MamanBarPrivate *priv;

/* class */
struct _MamanBarClass
GObjectClass parent_class;

/* class members */

/* Virtual public method */
void (*do_action_virt) (MamanBar *self, gchar *msg);


* Non-virtual public method
void maman_bar_do_action (MamanBar *self, gchar *msg /*, other params */);

/* Virtual method call declaration */
void maman_bar_do_action_virt (MamanBar *self, gchar *msg /*, other params */);
/* Virtual method default 'super' class method */
void maman_bar_do_action_virt_default (MamanBar *self, gchar *msg);

#endif /* __MAMAN_BAR_H__ */


#include "maman-bar.h"


A convenience macro for type implementations, which declares a class
initialization function, an instance initialization function (see GTypeInfo
for information about these) and a static variable named t_n_parent_class
pointing to the parent class. Furthermore, it defines a *_get_type()
function. See G_DEFINE_TYPE_EXTENDED() for an example.
G_DEFINE_TYPE (MamanBar, maman_bar, G_TYPE_OBJECT);

/* Define the private structure in the .c file */

struct _MamanBarPrivate
int hsize;
gchar *msg;

/* Init functions */
static void
maman_bar_class_init (MamanBarClass *klass)
g_type_class_add_private (klass, sizeof (MamanBarPrivate));

/* Setup the default handler for virtual method */
klass->do_action_virt = maman_bar_do_action_virt_default;

static void
maman_bar_init (MamanBar *self)

g_print("maman_bar_init() - init object\n");

/* Initialize all public and private members to reasonable default values. */

/* Initialize public fields */
self->public_int = 99;

g_print(" initializing public_int to %d\n", self->public_int);

/* Initialize private fields */
MamanBarPrivate *priv;
self->priv = priv = MAMAN_BAR_GET_PRIVATE(self);
priv->hsize = 42;

g_print(" init'd private variable priv->hsize to %d\n", priv->hsize);

/* If you need specific construction properties to complete initialization,
* delay initialization completion until the property is set.


/* Object non-virtual method */
void maman_bar_do_action (MamanBar *self, gchar *msg) {
/* First test that 'self' is of the correct type */
g_return_if_fail (MAMAN_IS_BAR (self));

// Assign to private 'msg'
self->priv->msg = msg;

g_print("maman_bar_do_action() - %s\n", self->priv->msg);


/* Object virtual method call - performs the override */
void maman_bar_do_action_virt (MamanBar *self, gchar *msg) {
/* First test that 'self' is of the correct type */
g_return_if_fail (MAMAN_IS_BAR (self));

g_print("maman_bar_do_action_virt() -> ");
MAMAN_BAR_GET_CLASS (self)->do_action_virt(self, msg);

/* Object virtual method default action (can be overridden) */
void maman_bar_do_action_virt_default (MamanBar *self, gchar *msg) {

g_print("maman_bar_do_action_virt_default() - %s\n", msg );


main (int argc, char *argv[])
* Prior to any use of the type system, g_type_init() has to be called
* to initialize the type system and assorted other code portions
* (such as the various fundamental type implementations or the signal
* system).

/* Create our object */
MamanBar *bar = g_object_new (MAMAN_TYPE_BAR, NULL);

bar->public_int +=1;
g_print("incremented bar->public_int: %d\n", bar->public_int);

/* Call object method */
maman_bar_do_action(bar, "helowrld");

/* Call virtual object method - we could subclass and override... */
maman_bar_do_action_virt(bar, "HELOWRLD");

return 0;

And here's what I get when I run a.out:
ok ./a.out
maman_bar_init() - init object
initializing public_int to 99
init'd private variable priv->hsize to 42
incremented bar->public_int: 100
maman_bar_do_action() - helowrld
maman_bar_do_action_virt() -> maman_bar_do_action_virt_default() - HELOWRLD
You can download the source files directly from here.


  1. Your working GObject example is a great help. I've been working on getting a small DBus/Glib demonstration together and this completed the picture for me. Many thanks!

  2. Hello JA,

    Your tutorial was VERY helpful for me, thank you:-)) I am trying though to implement the singleton as described here:

    but it does not behave as a singleton for me.
    I do the following(pseudo-code):
    single1 = g_object_new(MY_TYPE_SINGLE,...);
    my_single_set_foo(single1, 10);
    single2 = g_object_new(MY_TYPE_SINGLE...);
    int foo = my_single_get_foo(single2);

    but 'foo' is not 10.
    do you have any idea?

  3. Great job! It really helped me! You could add some properties to demonstrate how they work though

  4. I guess I *have* been ignoring the blog for a while. Sorry I didn't see the comments earlier.

    simonbolek, I'm not entirely sure, but on first blush I'd say be certain that you're doing what they propose in Example 1 at the URL you provided, in the constructor function - maman_bar_init().

    Line 15 of Example 1 should probably be something like:

    the_singleton = MAMAN_BAR (object);

  5. This doesn't work on linux mint for me..

    gcc `pkg-config --libs gtk+-2.0` `pkg-config --cflags gtk+-2.0` maman-bar.c

    dies with a bunch of linker errors similar to this:
    "undefined reference to `g_type_class_peek_parent'"

    this does..
    gcc `pkg-config --cflags gtk+-2.0` maman-bar.c `pkg-config --libs gtk+-2.0`

    ... for newbies.

    1. Also thanks for putting the code up. I've found it quite fiddly to get right from the code snippets.

  6. hi, I added a comment in
    hoping that your files may become part of the official tutorial