Define G_DEFINE_DYNAMIC_TYPE and and _EXTENDED variant. (#334437)
authorMatthias Clasen <mclasen@redhat.com>
Fri, 29 Dec 2006 06:12:11 +0000 (06:12 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Fri, 29 Dec 2006 06:12:11 +0000 (06:12 +0000)
2006-12-29 Matthias Clasen  <mclasen@redhat.com>

        * gtypemodule.h: Define G_DEFINE_DYNAMIC_TYPE and
        and _EXTENDED variant.  (#334437)

ChangeLog
docs/reference/ChangeLog
docs/reference/gobject/gobject-docs.sgml
docs/reference/gobject/gobject-sections.txt
docs/reference/gobject/tmpl/gtypemodule.sgml
gobject/ChangeLog
gobject/gtypemodule.h
tests/gobject/Makefile.am
tests/gobject/dynamictype.c [new file with mode: 0644]

index 989f8d9..ddaf5ad 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2006-12-29  Matthias Clasen  <mclasen@redhat.com>
+
+       * tests/gobject/Makefile.am:
+       * tests/gobject/dynamictype.c: New test for dynamic type 
+       registration macros. 
+
 Thu Dec 28 21:14:45 2006  Tim Janik  <timj@imendio.com>
 
        * glib/gslice.c: removed pthread-dependant debugging bits, the code
index 18afe00..4ac9748 100644 (file)
@@ -1,5 +1,15 @@
 2006-12-28  Matthias Clasen  <mclasen@redhat.com>
 
+       * 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  <mclasen@redhat.com>
+
        * gobject/tmpl/objects.sgml: Clarify a detail about
        g_object_set_data_full.  (#343750, Christian Neumair)
 
index 2a536b8..5b01ea0 100644 (file)
   <index role="2.12">
     <title>Index of new symbols in 2.12</title>
   </index>  
+  <index role="2.14">
+    <title>Index of new symbols in 2.14</title>
+  </index>  
   
 </book>
index 43f12e0..a9961a3 100644 (file)
@@ -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
+
 <SUBSECTION Standard>
 G_TYPE_MODULE
 G_IS_TYPE_MODULE
index 38240f7..550d2dd 100644 (file)
@@ -196,3 +196,96 @@ not be unloaded.
   members being 0.
 
 
+<!-- ##### MACRO G_DEFINE_DYNAMIC_TYPE ##### -->
+<para>
+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 <function>*_get_type()</function> and a static 
+<function>*_register_type()</function> function for use in your
+<function>module_init()</function>.
+See G_DEFINE_DYNAMIC_TYPE_EXTENDED() for an example.
+</para>
+
+@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
+
+
+<!-- ##### MACRO G_DEFINE_DYNAMIC_TYPE_EXTENDED ##### -->
+<para>
+A more general version of G_DEFINE_DYNAMIC_TYPE() which
+allows to specify #GTypeFlags and custom code.
+</para>
+<informalexample><programlisting>
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (GtkGadget,
+                                gtk_gadget,
+                                GTK_TYPE_THING,
+                                0,
+                                G_IMPLEMENT_INTERFACE (TYPE_GIZMO,
+                                                       gtk_gadget_gizmo_init));
+</programlisting>
+expands to
+<programlisting>
+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,
+                                                    &amp;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, &amp;g_implement_interface_info);
+  }
+}
+</programlisting>
+</informalexample>
+
+@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
+
index 6a266ec..8de6d4e 100644 (file)
@@ -1,3 +1,8 @@
+2006-12-29 Matthias Clasen  <mclasen@redhat.com>
+
+       * gtypemodule.h: Define G_DEFINE_DYNAMIC_TYPE and
+       and _EXTENDED variant.  (#334437)
+
 Fri Dec 15 2006  Matthias Clasen  <mclasen@redhat.com>
 
        * gtype.c (instance_real_class_get): Dereference the pointer 
index 7809c95..a992389 100644 (file)
@@ -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);
index 09be339..8acc7e2 100644 (file)
@@ -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 (file)
index 0000000..2a5415e
--- /dev/null
@@ -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 <glib-object.h>
+
+#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;
+}