Re: help a newbie with GObject
- From: David Nečas (Yeti) <yeti physics muni cz>
- To: gtk-list gnome org
- Subject: Re: help a newbie with GObject
- Date: Sun, 6 Aug 2006 02:51:27 +0200
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]