From d7b7c44e4012ed6a5f7343293db70ac2b3b29acd Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 29 Dec 2006 06:12:11 +0000 Subject: [PATCH] Define G_DEFINE_DYNAMIC_TYPE and and _EXTENDED variant. (#334437) 2006-12-29 Matthias Clasen * gtypemodule.h: Define G_DEFINE_DYNAMIC_TYPE and and _EXTENDED variant. (#334437) --- ChangeLog | 6 + docs/reference/ChangeLog | 10 ++ docs/reference/gobject/gobject-docs.sgml | 3 + docs/reference/gobject/gobject-sections.txt | 4 + docs/reference/gobject/tmpl/gtypemodule.sgml | 93 +++++++++++++ gobject/ChangeLog | 5 + gobject/gtypemodule.h | 41 ++++++ tests/gobject/Makefile.am | 1 + tests/gobject/dynamictype.c | 130 +++++++++++++++++++ 9 files changed, 293 insertions(+) create mode 100644 tests/gobject/dynamictype.c diff --git a/ChangeLog b/ChangeLog index 989f8d9b0..ddaf5adfa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-12-29 Matthias Clasen + + * tests/gobject/Makefile.am: + * tests/gobject/dynamictype.c: New test for dynamic type + registration macros. + Thu Dec 28 21:14:45 2006 Tim Janik * glib/gslice.c: removed pthread-dependant debugging bits, the code diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 18afe0076..4ac974851 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,13 @@ +2006-12-28 Matthias Clasen + + * gobject/tmpl/gtype.sgml: Updates + + * gobject/tmpl/gtypemodule.sgml: Document dynamic type + registration macros. + + * gobject/gobject-docs.sgml: Add "Since 2.14" index + * gobject/gobject-sections.txt: Add dynamic type macros + 2006-12-28 Matthias Clasen * gobject/tmpl/objects.sgml: Clarify a detail about diff --git a/docs/reference/gobject/gobject-docs.sgml b/docs/reference/gobject/gobject-docs.sgml index 2a536b890..5b01ea090 100644 --- a/docs/reference/gobject/gobject-docs.sgml +++ b/docs/reference/gobject/gobject-docs.sgml @@ -145,5 +145,8 @@ Index of new symbols in 2.12 + + Index of new symbols in 2.14 + diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 43f12e0f8..a9961a324 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -199,6 +199,10 @@ g_type_module_register_type g_type_module_add_interface g_type_module_register_enum g_type_module_register_flags + +G_DEFINE_DYNAMIC_TYPE +G_DEFINE_DYNAMIC_TYPE_EXTENDED + G_TYPE_MODULE G_IS_TYPE_MODULE diff --git a/docs/reference/gobject/tmpl/gtypemodule.sgml b/docs/reference/gobject/tmpl/gtypemodule.sgml index 38240f7fc..550d2dde6 100644 --- a/docs/reference/gobject/tmpl/gtypemodule.sgml +++ b/docs/reference/gobject/tmpl/gtypemodule.sgml @@ -196,3 +196,96 @@ not be unloaded. members being 0. + + +A convenience macro for dynamic type implementations, which declares a +class initialization function, an instance initialization function (see +#GTypeInfo for information about these) and a static variable named +@t_n_parent_class pointing to the parent class. Furthermore, +it defines a *_get_type() and a static +*_register_type() function for use in your +module_init(). +See G_DEFINE_DYNAMIC_TYPE_EXTENDED() for an example. + + +@TN: The name of the new type, in Camel case. +@t_n: The name of the new type, in lowercase, with words + separated by '_'. +@T_P: The #GType of the parent type. + +@Since: 2.14 + + + + +A more general version of G_DEFINE_DYNAMIC_TYPE() which +allows to specify #GTypeFlags and custom code. + + +G_DEFINE_DYNAMIC_TYPE_EXTENDED (GtkGadget, + gtk_gadget, + GTK_TYPE_THING, + 0, + G_IMPLEMENT_INTERFACE (TYPE_GIZMO, + gtk_gadget_gizmo_init)); + +expands to + +static void gtk_gadget_init (GtkGadget *self); +static void gtk_gadget_class_init (GtkGadgetClass *klass); +static void gtk_gadget_class_finalize (GtkGadgetClass *klass); + +static gpointer gtk_gadget_parent_class = NULL; +static GType gtk_gadget_type_id = 0; + +static void gtk_gadget_class_intern_init (gpointer klass) +{ + gtk_gadget_parent_class = g_type_class_peek_parent (klass); + gtk_gadget_class_init ((GtkGadgetClass*) klass); +} + +GType +gtk_gadget_get_type (void) +{ + return gtk_gadget_type_id; +} + +static void +gtk_gadget_register_type (GTypeModule *type_module) +{ + const GTypeInfo g_define_type_info = { + sizeof (GtkGadgetClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gtk_gadget_class_intern_init, + (GClassFinalizeFunc) gtk_gadget_class_finalize, + NULL, /* class_data */ + sizeof (GtkGadget), + 0, /* n_preallocs */ + (GInstanceInitFunc) gtk_gadget_init, + NULL /* value_table */ + }; + gtk_gadget_type_id = g_type_module_register_type (type_module, + GTK_TYPE_THING, + GtkGadget, + &g_define_type_info, + (GTypeFlags) flags); + { + const GInterfaceInfo g_implement_interface_info = { + (GInterfaceInitFunc) gtk_gadget_gizmo_init + }; + g_type_add_interface_static (g_define_type_id, TYPE_GIZMO, &g_implement_interface_info); + } +} + + + +@TypeName: The name of the new type, in Camel case. +@type_name: The name of the new type, in lowercase, with words + separated by '_'. +@TYPE_PARENT: The #GType of the parent type. +@flags: #GTypeFlags to pass to g_type_register_static() +@CODE: Custom code that gets inserted in the *_get_type() function. + +@Since: 2.14 + diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 6a266ec50..8de6d4ea3 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,8 @@ +2006-12-29 Matthias Clasen + + * gtypemodule.h: Define G_DEFINE_DYNAMIC_TYPE and + and _EXTENDED variant. (#334437) + Fri Dec 15 2006 Matthias Clasen * gtype.c (instance_real_class_get): Dereference the pointer diff --git a/gobject/gtypemodule.h b/gobject/gtypemodule.h index 7809c9599..a99238976 100644 --- a/gobject/gtypemodule.h +++ b/gobject/gtypemodule.h @@ -66,6 +66,47 @@ struct _GTypeModuleClass void (*reserved4) (void); }; +#define G_DEFINE_DYNAMIC_TYPE(TN, t_n, T_P) G_DEFINE_DYNAMIC_TYPE_EXTENDED (TN, t_n, T_P, 0, {}) +#define G_DEFINE_DYNAMIC_TYPE_EXTENDED(TypeName, type_name, TYPE_PARENT, flags, CODE) \ +static void type_name##_init (TypeName *self); \ +static void type_name##_class_init (TypeName##Class *klass); \ +static void type_name##_class_finalize (TypeName##Class *klass); \ +static gpointer type_name##_parent_class = NULL; \ +static GType type_name##_type_id = 0; \ +static void type_name##_class_intern_init (gpointer klass) \ +{ \ + type_name##_parent_class = g_type_class_peek_parent (klass); \ + type_name##_class_init ((TypeName##Class*) klass); \ +} \ +GType \ +type_name##_get_type (void) \ +{ \ + return type_name##_type_id; \ +} \ +static void \ +type_name##_register_type (GTypeModule *type_module) \ +{ \ + const GTypeInfo g_define_type_info = { \ + sizeof (TypeName##Class), \ + (GBaseInitFunc) NULL, \ + (GBaseFinalizeFunc) NULL, \ + (GClassInitFunc) type_name##_class_intern_init, \ + (GClassFinalizeFunc) type_name##_class_finalize, \ + NULL, /* class_data */ \ + sizeof (TypeName), \ + 0, /* n_preallocs */ \ + (GInstanceInitFunc) type_name##_init, \ + NULL /* value_table */ \ + }; \ + type_name##_type_id = g_type_module_register_type (type_module, \ + TYPE_PARENT, \ + #TypeName, \ + &g_define_type_info, \ + (GTypeFlags) flags); \ + { CODE ; } \ +} + + GType g_type_module_get_type (void) G_GNUC_CONST; gboolean g_type_module_use (GTypeModule *module); void g_type_module_unuse (GTypeModule *module); diff --git a/tests/gobject/Makefile.am b/tests/gobject/Makefile.am index 09be33952..8acc7e25e 100644 --- a/tests/gobject/Makefile.am +++ b/tests/gobject/Makefile.am @@ -51,6 +51,7 @@ test_programs = \ paramspec-test \ accumulator \ defaultiface \ + dynamictype \ ifacecheck \ ifaceinit \ ifaceinherit \ diff --git a/tests/gobject/dynamictype.c b/tests/gobject/dynamictype.c new file mode 100644 index 000000000..2a5415e43 --- /dev/null +++ b/tests/gobject/dynamictype.c @@ -0,0 +1,130 @@ +/* GObject - GLib Type, Object, Parameter and Signal Library + * Copyright (C) 2001, 2003 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "TestDynamicType" + +#undef G_DISABLE_ASSERT +#undef G_DISABLE_CHECKS +#undef G_DISABLE_CAST_CHECKS + +#include + +#include "testcommon.h" +#include "testmodule.h" + +/* This test tests the macros for defining dynamic types. + */ + +static gboolean loaded = FALSE; + +#define DYNAMIC_OBJECT_TYPE (dynamic_object_get_type ()) + +typedef GObject DynamicObject; +typedef struct _DynamicObjectClass DynamicObjectClass; + +struct _DynamicObjectClass +{ + GObjectClass parent_class; + guint val; +}; + +G_DEFINE_DYNAMIC_TYPE(DynamicObject, dynamic_object, G_TYPE_OBJECT); + +static void +dynamic_object_class_init (DynamicObjectClass *class) +{ + class->val = 42; + loaded = TRUE; +} + +static void +dynamic_object_class_finalize (DynamicObjectClass *class) +{ + loaded = FALSE; +} + +static void +dynamic_object_init (DynamicObject *dynamic_object) +{ +} + + +static void +module_register (GTypeModule *module) +{ + dynamic_object_register_type (module); +} + +static void +test_dynamic_type (void) +{ + GTypeModule *module; + DynamicObjectClass *class; + + module = test_module_new (module_register); + + /* Not loaded until we call ref for the first time */ + class = g_type_class_peek (DYNAMIC_OBJECT_TYPE); + g_assert (class == NULL); + g_assert (!loaded); + + /* Ref loads */ + class = g_type_class_ref (DYNAMIC_OBJECT_TYPE); + g_assert (class && class->val == 42); + g_assert (loaded); + + /* Peek then works */ + class = g_type_class_peek (DYNAMIC_OBJECT_TYPE); + g_assert (class && class->val == 42); + g_assert (loaded); + + /* Unref causes finalize */ + g_type_class_unref (class); + + /* Peek returns NULL */ + class = g_type_class_peek (DYNAMIC_OBJECT_TYPE); + g_assert (!class); + g_assert (!loaded); + + /* Ref reloads */ + class = g_type_class_ref (DYNAMIC_OBJECT_TYPE); + g_assert (class && class->val == 42); + g_assert (loaded); + + /* And Unref causes finalize once more*/ + g_type_class_unref (class); + class = g_type_class_peek (DYNAMIC_OBJECT_TYPE); + g_assert (!class); + g_assert (!loaded); +} + +int +main (int argc, + char *argv[]) +{ + g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) | + G_LOG_LEVEL_WARNING | + G_LOG_LEVEL_CRITICAL); + g_type_init (); + + test_dynamic_type (); + + return 0; +}