Define G_DEFINE_DYNAMIC_TYPE and and _EXTENDED variant. (#334437)

2006-12-29 Matthias Clasen  <mclasen@redhat.com>

        * gtypemodule.h: Define G_DEFINE_DYNAMIC_TYPE and
        and _EXTENDED variant.  (#334437)
This commit is contained in:
Matthias Clasen 2006-12-29 06:12:11 +00:00 committed by Matthias Clasen
parent b1e4310d6f
commit d7b7c44e40
9 changed files with 293 additions and 0 deletions

View File

@ -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

View File

@ -1,3 +1,13 @@
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

View File

@ -145,5 +145,8 @@
<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>

View 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

View 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

View 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

View 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);

View File

@ -51,6 +51,7 @@ test_programs = \
paramspec-test \
accumulator \
defaultiface \
dynamictype \
ifacecheck \
ifaceinit \
ifaceinherit \

130
tests/gobject/dynamictype.c Normal file
View File

@ -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;
}