+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
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 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>
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
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,
+ &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);
+ }
+}
+</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
+
+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
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);
paramspec-test \
accumulator \
defaultiface \
+ dynamictype \
ifacecheck \
ifaceinit \
ifaceinherit \
--- /dev/null
+/* 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;
+}