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 989f8d9..ddaf5ad 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 18afe00..4ac9748 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,5 +1,15 @@ 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 g_object_set_data_full. (#343750, Christian Neumair) diff --git a/docs/reference/gobject/gobject-docs.sgml b/docs/reference/gobject/gobject-docs.sgml index 2a536b8..5b01ea0 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 43f12e0..a9961a3 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 38240f7..550d2dd 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 6a266ec..8de6d4e 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 7809c95..a992389 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 09be339..8acc7e2 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 0000000..2a5415e --- /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; +} -- 2.7.4