mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
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:
parent
b1e4310d6f
commit
d7b7c44e40
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
&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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -51,6 +51,7 @@ test_programs = \
|
||||
paramspec-test \
|
||||
accumulator \
|
||||
defaultiface \
|
||||
dynamictype \
|
||||
ifacecheck \
|
||||
ifaceinit \
|
||||
ifaceinherit \
|
||||
|
130
tests/gobject/dynamictype.c
Normal file
130
tests/gobject/dynamictype.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user