Last active
October 16, 2019 01:29
-
-
Save igormorgado/2525b56c2e4e8bab75dcf8848d2a2bc3 to your computer and use it in GitHub Desktop.
Simple GObject usage.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
How to use G_DECLARE_DERIVATIVE_TYPE and/or G_DECLARE_FINAL_TYPE in this code to reduce the "boilerplate code"? | |
Right now, errors building the code: | |
pet-dog.c: In function ‘pet_dog_print’: | |
pet-dog.c:17:36: error: invalid type argument of ‘->’ (have ‘PetBaseClass’ {aka ‘struct _PetBaseClass’}) | |
PET_DOG_GET_CLASS(self)->parent->print(self); | |
^~ | |
pet-dog.c: In function ‘pet_dog_class_init’: | |
pet-dog.c:86:27: warning: assignment to ‘void (*)(PetBase *)’ {aka ‘void (*)(struct _PetBase *)’} from incompatible pointer type ‘void (*)(PetDog *)’ {aka ‘void (*)(struct _PetDog *)’} [-Wincompatible-pointer-types] | |
pet_base_class->sound = pet_dog_sound_real; | |
^ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "pet-dog.h" | |
int | |
main(int argc, char *argv[]) | |
{ | |
PetBase * generic_pet = pet_base_new (); | |
/* | |
* Is there any better way to set properties | |
* in GObject | |
*/ | |
GValue age = G_VALUE_INIT; | |
g_value_init(&age, G_TYPE_INT); | |
g_value_set_int(&age, 42); | |
g_object_set_property(G_OBJECT(generic_pet), "age", &age); | |
GValue name = G_VALUE_INIT; | |
g_value_init(&name, G_TYPE_STRING); | |
g_value_set_string(&name, "REX"); | |
g_object_set_property(G_OBJECT(generic_pet), "name", &name); | |
pet_base_print(generic_pet); | |
pet_base_sound(generic_pet); | |
PetBase *another_pet = g_object_new(PET_TYPE_BASE, "age", 18, "name", "BOB", NULL); | |
pet_base_print(another_pet); | |
pet_base_sound(another_pet); | |
PetDog *dog_pet = g_object_new(PET_TYPE_DOG, "age", 22, "name", "FRUX", "toy", "BONE", NULL); | |
pet_dog_print(dog_pet); | |
pet_dog_sound(dog_pet); | |
g_object_unref(dog_pet); | |
g_object_unref(another_pet); | |
g_object_unref(generic_pet); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: | |
gcc -ggdb -g `pkg-config --cflags --libs glib-2.0` `pkg-config --cflags --libs gobject-2.0` -I. -g -o pets main.c pet-base.c pet-dog.c | |
clean: | |
rm -rf pets |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "pet-base.h" | |
static void pet_base_init (PetBase *self); | |
G_DEFINE_TYPE (PetBase, pet_base, G_TYPE_OBJECT) | |
enum { | |
PROP_0, | |
PROP_AGE, | |
PROP_NAME, | |
N_PROPS | |
}; | |
void pet_base_sound(PetBase *self) | |
{ | |
PET_BASE_GET_CLASS(self)->sound(self); | |
} | |
void pet_base_print(PetBase *self) | |
{ | |
PET_BASE_GET_CLASS(self)->print(self); | |
} | |
PetBase * | |
pet_base_new(void) | |
{ | |
return g_object_new (PET_TYPE_BASE, NULL); | |
} | |
static void | |
pet_base_finalize (GObject *object) | |
{ | |
PetBase *self = (PetBase *)object; | |
G_OBJECT_CLASS (pet_base_parent_class)->finalize (object); | |
} | |
static void | |
pet_base_sound_real (PetBase *self) | |
{ | |
g_print("Anonymous pet makes no sound.\n"); | |
} | |
static void | |
pet_base_print_real (PetBase *self) | |
{ | |
g_print("I'm "); | |
if (self->name->str) | |
g_print("%s ", self->name->str); | |
else | |
g_print("nobody "); | |
g_print("and have %d years old.\n", self->age); | |
} | |
static void | |
pet_base_get_property (GObject *object, | |
guint prop_id, | |
GValue *value, | |
GParamSpec *pspec) | |
{ | |
PetBase *self = PET_BASE (object); | |
switch (prop_id) { | |
case PROP_NAME: | |
g_value_set_string(value, self->name->str); | |
break; | |
case PROP_AGE: | |
g_value_set_int(value, self->age); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
} | |
} | |
static void | |
pet_base_set_property (GObject *object, | |
guint prop_id, | |
const GValue *value, | |
GParamSpec *pspec) | |
{ | |
PetBase *self = PET_BASE (object); | |
switch (prop_id) { | |
case PROP_NAME: { | |
const char * new_name = g_value_get_string(value); | |
g_string_assign(self->name, new_name); | |
break; | |
} | |
case PROP_AGE: { | |
gint new_age = g_value_get_int(value); | |
self->age = new_age; | |
break; | |
} | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | |
break; | |
} | |
} | |
static void | |
pet_base_class_init (PetBaseClass *klass) | |
{ | |
GObjectClass *object_class = G_OBJECT_CLASS (klass); | |
GParamSpec *name_param; | |
GParamSpec *age_param; | |
object_class->finalize = pet_base_finalize; | |
object_class->get_property = pet_base_get_property; | |
object_class->set_property = pet_base_set_property; | |
klass->sound = pet_base_sound_real; | |
klass->print = pet_base_print_real; | |
age_param = g_param_spec_int("age", // name | |
"age", // nick | |
"pet age in years", // Blurb | |
0, // Minimum | |
INT_MAX, // Maximum | |
0, // Default value | |
G_PARAM_READWRITE); // Flags | |
name_param = g_param_spec_string("name", | |
"name", | |
"pet name", | |
NULL, | |
G_PARAM_READWRITE); | |
g_object_class_install_property( | |
object_class, | |
PROP_AGE, | |
age_param); | |
g_object_class_install_property( | |
object_class, | |
PROP_NAME, | |
name_param); | |
} | |
static void | |
pet_base_init (PetBase *self) | |
{ | |
self->age = 0; | |
self->name = g_string_new(NULL); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __PET_BASE_H__ | |
#define __PET_BASE_H__ | |
#include <glib-object.h> | |
G_BEGIN_DECLS | |
GType pet_base_get_type (void); | |
//G_DECLARE_DERIVABLE_TYPE (PetBase, pet_base, PET, BASE, GObject) | |
typedef struct _PetBase PetBase; | |
typedef struct _PetBaseClass PetBaseClass; | |
#define PET_TYPE_BASE (pet_base_get_type()) | |
#define PET_BASE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PET_TYPE_BASE, PetBase)) | |
#define PET_BASE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), PET_TYPE_BASE, PetBaseClass)) | |
#define IS_PET_BASE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PET_TYPE_BASE)) | |
#define IS_PET_BASE_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), PET_TYPE_BASE)) | |
#define PET_BASE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PET_TYPE_BASE, PetBaseClass)) | |
struct _PetBaseClass | |
{ | |
GObjectClass parent; | |
void (*sound) (PetBase *self); | |
void (*print) (PetBase *self); | |
}; | |
struct _PetBase | |
{ | |
GObject parent; | |
gint age; | |
GString *name; | |
}; | |
PetBase *pet_base_new (void); | |
void pet_base_sound (PetBase *self); | |
void pet_base_print (PetBase *self); | |
G_END_DECLS | |
#endif /* __PET_BASE_H__ */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include "pet-dog.h" | |
static void pet_dog_init (PetDog *self); | |
G_DEFINE_TYPE (PetDog, pet_dog, G_TYPE_OBJECT) | |
enum { | |
PROP_0, | |
PROP_TOY, | |
}; | |
void | |
pet_dog_print(PetDog *self) | |
{ | |
PET_DOG_GET_CLASS(self)->parent->print(self); | |
} | |
static void | |
pet_dog_sound_real (PetDog *self) | |
{ | |
g_print("Bark! Bark!\n"); | |
} | |
PetDog * | |
pet_dog_new(void) | |
{ | |
return g_object_new (PET_TYPE_DOG, NULL); | |
} | |
static void | |
pet_dog_get_property (GObject *object, | |
guint prop_id, | |
GValue *value, | |
GParamSpec *pspec) | |
{ | |
PetDog *self = PET_DOG(object); | |
switch (prop_id) { | |
case PROP_TOY: | |
g_value_set_string(value, self->toy->str); | |
break; | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | |
break; | |
} | |
} | |
static void | |
pet_dog_set_property (GObject *object, | |
guint prop_id, | |
const GValue *value, | |
GParamSpec *pspec) | |
{ | |
PetDog *self = PET_DOG(object); | |
switch (prop_id) { | |
case PROP_TOY: { | |
const char * new_toy = g_value_get_string(value); | |
g_string_assign(self->toy, new_toy); | |
break; | |
} | |
default: | |
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); | |
break; | |
} | |
} | |
static void | |
pet_dog_class_init (PetDogClass *klass) | |
{ | |
GObjectClass *object_class = G_OBJECT_CLASS(klass); | |
// GLib-GObject-WARNING **: invalid class cast from 'PetDog' to 'PetBase' | |
PetBaseClass *pet_base_class = PET_BASE_CLASS(klass); | |
GParamSpec *toy_param; | |
object_class->get_property = pet_dog_get_property; | |
object_class->set_property = pet_dog_set_property; | |
pet_base_class->sound = pet_dog_sound_real; | |
toy_param = g_param_spec_string("toy", | |
"toy", | |
"favorite toy", | |
NULL, | |
G_PARAM_READWRITE); | |
g_object_class_install_property( | |
object_class, | |
PROP_TOY, | |
toy_param); | |
} | |
static void | |
pet_dog_init (PetDog *self) | |
{ | |
// By default all dogs like their balls | |
self->toy = g_string_new("ball"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __PET_DOG_H__ | |
#define __PET_DOG_H__ | |
#include <glib-object.h> | |
#include "pet-base.h" | |
G_BEGIN_DECLS | |
GType pet_dog_get_type (void); | |
//G_DECLARE_FINAL_TYPE (PetDog, pet_dog, PET, DOG, PetBase) | |
typedef struct _PetDog PetDog; | |
typedef struct _PetDogClass PetDogClass; | |
#define PET_TYPE_DOG (pet_dog_get_type ()) | |
#define PET_DOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PET_TYPE_DOG, PetDog)) | |
#define PET_DOG_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), PET_TYPE_DOG, PetDogClass)) | |
#define IS_PET_DOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PET_TYPE_DOG)) | |
#define IS_PET_DOG_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), PET_TYPE_DOG)) | |
#define PET_DOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PET_TYPE_DOG, PetDogClass)) | |
struct _PetDogClass | |
{ | |
PetBaseClass parent; | |
void (*catch) (PetDog *self); | |
}; | |
// It inherits parent->age and parent->name | |
struct _PetDog | |
{ | |
PetBase parent; | |
GString *toy; | |
}; | |
PetDog *pet_dog_new (void); | |
void pet_dog_sound (PetDog *self); | |
void pet_dog_print (PetDog *self); | |
G_END_DECLS | |
#endif /* __PET_DOG_H__ */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment