Re: help a newbie with GObject



On Sun, Aug 06, 2006 at 02:11:51AM +0300, Alex Nedelcu wrote:
> I am trying to wrap my head around the GObject/GType system, but because
> of the lack of good documentation I am having trouble understanding it.
> 
> Do you know any good tutorial on GObject ?
> I found the tutorial available on developer.gnome.org
> (http://www.le-hacker.org/papers/gobject/) not for newbies.

The tutorial is now a part of GObject API documentation --
and it is good if you ask.  In fact I cannot imagine what do
you mean by the `lack of good documentation'.

> So I figured that the best way to understand anything is too have a
> working equivalent of something I can understand.

In my opinion to understand GObject one should forget the
object oriented mumbo jumbo for a while and view both
classes and instances and the plain C structs they
physically are and how they contain their parents like
a matryoshka.  That is to imagine what

  struct _Child {
      Parent parent_instance;

      gint data_member;
  };

and

  struct _ChildClass {
      ParentClass parent_class;

      void (*method)(Child *child);
  };

actually means.  How [almost] everything else works clearly
follows from that.  The syntax is kind of baroque but a user
of Gtk+ should be already trained to it.

> Can someone be kind and translate the following Java classes in C using
> GObject ?
> 
> (I am guessing that it should be a trivial task for someone experienced
> with the GObject system)
> 
> Thanks in advance ...

I'm leaving out the boilerplate, it is well described in the
tutorial and it adds lots of code to read without any value
(I doubt I have ever written it manually, I just take it
from anotehr file and use s/// to change names).  I'm also
prefixing everything with my- (which is how namespaces are
made in C).

Also see Gtk+ source code -- Gtk+ is nothing more than
a large collection of GObject examples...

> 
> abstract class Animal
> {
> 	void feed()
> 	{
> 		print("Feeding some animal");
> 	}
> }

myanimal.h ================================================

struct _MyAnimalClass {
    GObjectClass parent_class;

    void (*feed)(MyAnimal *animal);
};

struct _MyAnimal {
    GObject parent_instance;

    /* empty */
};


void my_animal_feed(MyAnimal *animal);


myanimal.c ================================================

static void my_animal_feed_real(MyAnimal *animal);

G_DEFINE_ABSTRACT_TYPE(MyAnimal, my_animal, G_TYPE_OBJECT)

static void
my_animal_class_init(MyAnimalClass *klass)
{
    klass->feed = &my_animal_feed_real;
}

static void
my_animal_init(MyAnimal *animal)
{
    /* empty */
}

void
my_animal_feed(MyAnimal *animal)
{
    /* Generally the method must be tested for NULL, but
     * here we know it always exists */
    MY_ANIMAL_GET_CLASS(animal)->feed(animal);
}

static void
my_animal_feed_real(MyAnimal *animal)
{
    printf("Feeding some animal\n");
}

> class Dog extends Animal
> {
> 	static int legs = 4;
> 
> 	String name;
> 	int age;
> 
> 	public Dog(String name, int age)
> 	{
> 		this.name = name;
> 		this.age = age;
> 	}
> 	
> 	void feed()
> 	{
> 		print("Feeding a canine named " + this.name);
> 	}
> }

mydog.h ================================================

struct _MyDogClass {
    MyAnimalClass parent_class;

    gint legs;
};

struct _MyDog {
    MyAnimal parent_instance;

    GString *name;
    gint age;
}

MyDog* my_dog_new(const gchar *name, gint age);


mydog.c ================================================

static void my_dog_finalize(GObject *object);
static void my_dog_feed(MyAnimal *animal);

G_DEFINE_TYPE(MyDog, my_dog, MY_TYPE_DOG)

static void
my_dog_class_init(MyDogClass *klass)
{
    GObjectClass gobject_class = G_OBJECT_CLASS(klass);
    MyAnimalClass animal_class = MY_ANIMAL_CLASS(klass);

    gobject_class->finalize = &my_dog_finalize;
    animal_class->feed = &my_dog_feed;
    /* The semantics is not exactly the same */
    klass->legs = 4;
}

static void
my_dog_init(MyDog *dog)
{
    dog->name = g_string_new("");
}

static void
my_dog_finalize(GObject *object)
{
    MyDog *dog;

    dog = MY_DOG(object);
    g_string_free(dog->name, TRUE);

    /* Generally the method must be tested for NULL, but
     * here we know it always exists */
    G_OBJECT_CLASS(my_dog_parent_class)->finalize(object);
}

MyDog*
my_dog_new(const gchar *name,
           gint age)
{
    MyDog *dog;

    dog = g_object_new(MY_TYPE_DOG, NULL);
    g_string_assign(dog->name, name);
    dog->age = age;
    /* If MyDog registered name and age as properties we
     * could also do
     * dog = g_object_new(MY_TYPE_DOG, "name", name, "age", age, NULL);
     */

    return dog;
}

static void
my_dog_feed(MyAnimal *animal)
{
    MyDog *dog;

    dog = MY_DOG(animal);
    printf("Feeding a canine named %s\n", dog->name->str);
}

> // .......
> 
> Animal animals[] = {
> 	new Dog("Bella", 2),
> 	new Dog("Toto", 3)
> };
> 
> for (int i=0; i<animals.length; i++)
> 	animals[i].feed();

/* The array initialization above is too dynamic plain
 * old C, so just make two animals to demonstrate feed().
 *
 * Also, it is impossible to work with GObjects by _value_,
 * use pointers. */

static MyAnimal *animals[2];

animals[0] = MY_ANIMAL(my_dog_new("Bella", 2));
animals[1] = MY_ANIMAL(my_dog_new("Toto", 3));

for (i = 0; i < G_N_ELEMENTS(animals); i++)
    my_animal_feed(animals[i]);


Yeti


--
Anonyms eat their boogers.



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]