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. _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list