Skip to content

Instantly share code, notes, and snippets.

@igormorgado
Last active October 16, 2019 01:29
Show Gist options
  • Save igormorgado/2525b56c2e4e8bab75dcf8848d2a2bc3 to your computer and use it in GitHub Desktop.
Save igormorgado/2525b56c2e4e8bab75dcf8848d2a2bc3 to your computer and use it in GitHub Desktop.
Simple GObject usage.
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;
^
#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;
}
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
#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);
}
#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__ */
#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");
}
#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