From 558507bc5ac1422e78135915ee77641e20dfd46c Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Tue, 2 Sep 2003 17:57:22 +0000 Subject: [PATCH] added support for a "default vtable" per interface, that interface vtables Tue Sep 2 19:37:21 2003 Tim Janik * gtype.[hc]: added support for a "default vtable" per interface, that interface vtables are initialized from. the default vtable is initialized and finalized through class_init, class_finalize and class_data from the interfaces GTypeInfo struct. (type_data_last_unref_Wm): unload child plugin before unreffing parent type. testifaceinit.c: minor fixups. fixed up base_init() assertions, since with a default vtable, base_init() may be called multiple times. added default initializer to iface1. --- .../gobject/tmpl/enumerations_flags.sgml | 10 +-- docs/reference/gobject/tmpl/gtype.sgml | 5 ++ .../gobject/tmpl/param_value_types.sgml | 16 ++-- gobject/ChangeLog | 13 +++ gobject/gtype.c | 82 +++++++++++++---- gobject/gtype.h | 2 +- gobject/testifaceinit.c | 90 ++++++++++++++----- tests/gobject/ifaceinit.c | 90 ++++++++++++++----- 8 files changed, 233 insertions(+), 75 deletions(-) diff --git a/docs/reference/gobject/tmpl/enumerations_flags.sgml b/docs/reference/gobject/tmpl/enumerations_flags.sgml index 02d787171..6f9462ff2 100644 --- a/docs/reference/gobject/tmpl/enumerations_flags.sgml +++ b/docs/reference/gobject/tmpl/enumerations_flags.sgml @@ -154,7 +154,7 @@ Looks up a #GEnumValue by name. @enum_class: a #GEnumClass @name: the name to look up @Returns: the #GEnumValue with name @name, or %NULL if the enumeration doesn' -t have a member with that name +t have a member with that name @@ -165,7 +165,7 @@ Looks up a #GEnumValue by nickname. @enum_class: a #GEnumClass @nick: the nickname to look up @Returns: the #GEnumValue with nickname @nick, or %NULL if the enumeration doesn' -t have a member with that nickname +t have a member with that nickname @@ -174,7 +174,7 @@ Returns the first #GFlagsValue which is set in @value. @flags_class: a #GFlagsClass -@value: the value +@value: the value @Returns: the first #GFlagsValue which is set in @value, or %NULL if none is set @@ -186,7 +186,7 @@ Looks up a #GFlagsValue by name. @flags_class: a #GFlagsClass @name: the name to look up @Returns: the #GFlagsValue with name @name, or %NULL if there is no flag with -that name +that name @@ -197,7 +197,7 @@ Looks up a #GFlagsValue by nickname. @flags_class: a #GFlagsClass @nick: the nickname to look up @Returns: the #GFlagsValue with nickname @nick, or %NULL if there is no flag -with that nickname +with that nickname diff --git a/docs/reference/gobject/tmpl/gtype.sgml b/docs/reference/gobject/tmpl/gtype.sgml index eddb37129..605a11fd9 100644 --- a/docs/reference/gobject/tmpl/gtype.sgml +++ b/docs/reference/gobject/tmpl/gtype.sgml @@ -473,6 +473,7 @@ class_init function with g_type_class_add_private(). @g_type: the type identifying which private data to retrieve. @c_type: The C type for the private structure. + @@ -746,6 +747,7 @@ my_object_get_some_field (MyObject *my_object) @g_class: class structure for an instantiatable type @private_size: size of private structure. + Returns the #GTypeInterface structure of an interface to which the passed in @@ -1469,3 +1471,6 @@ mode: sgml sgml-parent-document: ("../gobject-docs.sgml" "book" "refsect2" "") End: --> + + + diff --git a/docs/reference/gobject/tmpl/param_value_types.sgml b/docs/reference/gobject/tmpl/param_value_types.sgml index da9afc54c..157a6c6ab 100644 --- a/docs/reference/gobject/tmpl/param_value_types.sgml +++ b/docs/reference/gobject/tmpl/param_value_types.sgml @@ -914,7 +914,7 @@ See g_param_spec_internal() for details on property names. @name: canonical name of the property specified @nick: nick name for the property specified @blurb: description of the property specified -@enum_type: a #GType derived from %G_TYPE_ENUM +@enum_type: a #GType derived from %G_TYPE_ENUM @default_value: default value for the property specified @flags: flags for the property specified @Returns: a newly created parameter specification @@ -979,7 +979,6 @@ properties. @flags_class: the #GFlagsClass for the flags @default_value: default value for the property specified - Creates a new #GParamSpecEnum instance specifying a %G_TYPE_FLAGS @@ -992,7 +991,7 @@ See g_param_spec_internal() for details on property names. @name: canonical name of the property specified @nick: nick name for the property specified @blurb: description of the property specified -@flags_type: a #GType derived from %G_TYPE_FLAGS +@flags_type: a #GType derived from %G_TYPE_FLAGS @default_value: default value for the property specified @flags: flags for the property specified @Returns: a newly created parameter specification @@ -1110,8 +1109,8 @@ This is an internal function introduced mainly for C marshallers. @value: a valid #GValue of type %G_TYPE_STRING @v_string: duplicated unowned string to be set - -@value: a valid #GValue + +@value: a valid #GValue @v_string: string to be set @@ -1172,7 +1171,6 @@ properties. @parent_instance: private #GParamSpec portion - Creates a new #GParamSpecParam instance specifying a %G_TYPE_PARAM @@ -1186,9 +1184,10 @@ See g_param_spec_internal() for details on property names. @nick: nick name for the property specified @blurb: description of the property specified @param_type: a #GType derived from %G_TYPE_PARAM -@default_value: default value for the property specified @flags: flags for the property specified @Returns: a newly created parameter specification + +@default_value: default value for the property specified @@ -1257,6 +1256,7 @@ The #GType of #GParamSpecBoxed. + A #GParamSpec derived structure that contains the meta data for boxed properties. @@ -1368,7 +1368,6 @@ A #GParamSpec derived structure that contains the meta data for pointer properti @parent_instance: private #GParamSpec portion - Creates a new #GParamSpecPoiner instance specifying a pointer property. @@ -1440,7 +1439,6 @@ A #GParamSpec derived structure that contains the meta data for object propertie @parent_instance: private #GParamSpec portion - Creates a new #GParamSpecBoxed instance specifying a %G_TYPE_OBJECT diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 6d3e511ce..a34f2ea0b 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,16 @@ +Tue Sep 2 19:37:21 2003 Tim Janik + + * gtype.[hc]: added support for a "default vtable" per interface, + that interface vtables are initialized from. + the default vtable is initialized and finalized through class_init, + class_finalize and class_data from the interfaces GTypeInfo struct. + (type_data_last_unref_Wm): unload child plugin before unreffing + parent type. + + testifaceinit.c: minor fixups. fixed up base_init() assertions, since + with a default vtable, base_init() may be called multiple times. + added default initializer to iface1. + Tue Sep 2 14:53:41 2003 Tim Janik * gobject-query.c (main): fix iterating over fundamental types. diff --git a/gobject/gtype.c b/gobject/gtype.c index 46a5c8bbd..2c78542d3 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -241,6 +241,10 @@ struct _IFaceData guint16 vtable_size; GBaseInitFunc vtable_init_base; GBaseFinalizeFunc vtable_finalize_base; + GClassInitFunc dflt_init; + GClassFinalizeFunc dflt_finalize; + gconstpointer dflt_data; + gpointer dflt_vtable; }; struct _ClassData { @@ -736,9 +740,9 @@ check_type_info_I (TypeNode *pnode, return FALSE; } /* check class & interface members */ - if (!(finfo->type_flags & G_TYPE_FLAG_CLASSED) && + if (!((finfo->type_flags & G_TYPE_FLAG_CLASSED) || is_interface) && (info->class_init || info->class_finalize || info->class_data || - (!is_interface && (info->class_size || info->base_init || info->base_finalize)))) + info->class_size || info->base_init || info->base_finalize)) { if (pnode) g_warning ("cannot create class for `%s', derived from non-classed parent type `%s'", @@ -985,6 +989,10 @@ type_data_make_W (TypeNode *node, data->iface.vtable_size = info->class_size; data->iface.vtable_init_base = info->base_init; data->iface.vtable_finalize_base = info->base_finalize; + data->iface.dflt_init = info->class_init; + data->iface.dflt_finalize = info->class_finalize; + data->iface.dflt_data = info->class_data; + data->iface.dflt_vtable = NULL; } else { @@ -1581,6 +1589,31 @@ g_type_free_instance (GTypeInstance *instance) g_type_class_unref (class); } +static void +type_iface_ensure_dflt_vtable_Wm (TypeNode *iface) +{ + g_assert (iface->data); + + if (!iface->data->iface.dflt_vtable) + { + GTypeInterface *vtable = g_malloc0 (iface->data->iface.vtable_size); + iface->data->iface.dflt_vtable = vtable; + vtable->g_type = NODE_TYPE (iface); + vtable->g_instance_type = 0; + if (iface->data->iface.vtable_init_base || + iface->data->iface.dflt_init) + { + G_WRITE_UNLOCK (&type_rw_lock); + if (iface->data->iface.vtable_init_base) + iface->data->iface.vtable_init_base (vtable); + if (iface->data->iface.dflt_init) + iface->data->iface.dflt_init (vtable, (gpointer) iface->data->iface.dflt_data); + G_WRITE_LOCK (&type_rw_lock); + } + } +} + + /* This is called to allocate and do the first part of initializing * the interface vtable; type_iface_vtable_iface_init_Wm() does the remainder. * @@ -1593,7 +1626,7 @@ static gboolean type_iface_vtable_base_init_Wm (TypeNode *iface, TypeNode *node) { - IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); + IFaceEntry *entry; IFaceHolder *iholder; GTypeInterface *vtable = NULL; TypeNode *pnode; @@ -1602,7 +1635,11 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), TRUE); if (!iholder) return FALSE; /* we don't modify write lock upon FALSE */ - + + type_iface_ensure_dflt_vtable_Wm (iface); + + entry = type_lookup_iface_entry_L (node, iface); + g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info); pnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); @@ -1614,7 +1651,7 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); } if (!vtable) - vtable = g_malloc0 (iface->data->iface.vtable_size); + vtable = g_memdup (iface->data->iface.dflt_vtable, iface->data->iface.vtable_size); entry->vtable = vtable; vtable->g_type = NODE_TYPE (iface); vtable->g_instance_type = NODE_TYPE (node); @@ -1622,8 +1659,7 @@ type_iface_vtable_base_init_Wm (TypeNode *iface, if (iface->data->iface.vtable_init_base) { G_WRITE_UNLOCK (&type_rw_lock); - if (iface->data->iface.vtable_init_base) - iface->data->iface.vtable_init_base (vtable); + iface->data->iface.vtable_init_base (vtable); G_WRITE_LOCK (&type_rw_lock); } return TRUE; /* initialized the vtable */ @@ -1930,7 +1966,6 @@ type_data_finalize_class_U (TypeNode *node, if (bnode->data->class.class_finalize_base) bnode->data->class.class_finalize_base (class); - class->g_type = 0; g_free (cdata->class); } @@ -1999,22 +2034,37 @@ type_data_last_unref_Wm (GType type, type_data_finalize_class_U (node, &tdata->class); G_WRITE_LOCK (&type_rw_lock); } + else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable) + { + node->mutatable_check_cache = FALSE; + node->data = NULL; + if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base) + { + G_WRITE_UNLOCK (&type_rw_lock); + if (tdata->iface.dflt_finalize) + tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data); + if (tdata->iface.vtable_finalize_base) + tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable); + G_WRITE_LOCK (&type_rw_lock); + } + g_free (tdata->iface.dflt_vtable); + } else - { - node->mutatable_check_cache = FALSE; - node->data = NULL; - } - - /* freeing tdata->common.value_table and its contents is taking care of + { + node->mutatable_check_cache = FALSE; + node->data = NULL; + } + + /* freeing tdata->common.value_table and its contents is taken care of * by allocating it in one chunk with tdata */ g_free (tdata); - if (ptype) - type_data_unref_Wm (lookup_type_node_I (ptype), FALSE); G_WRITE_UNLOCK (&type_rw_lock); g_type_plugin_unuse (node->plugin); G_WRITE_LOCK (&type_rw_lock); + if (ptype) + type_data_unref_Wm (lookup_type_node_I (ptype), FALSE); } } diff --git a/gobject/gtype.h b/gobject/gtype.h index 5aff33eff..c762c804a 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -234,7 +234,7 @@ struct _GTypeInfo GBaseInitFunc base_init; GBaseFinalizeFunc base_finalize; - /* classed types, instantiated types */ + /* interface types, classed types, instantiated types */ GClassInitFunc class_init; GClassFinalizeFunc class_finalize; gconstpointer class_data; diff --git a/gobject/testifaceinit.c b/gobject/testifaceinit.c index 94154ce1e..c25bb2968 100644 --- a/gobject/testifaceinit.c +++ b/gobject/testifaceinit.c @@ -28,7 +28,7 @@ * The test defines 5 interfaces: * * - TestIface1 is added before the class is initialized - * - TestIface2 is added in base_object_baes_init() + * - TestIface2 is added in base_object_base_init() * - TestIface3 is added in test_iface1_base_init() * - TestIface4 is added in test_object_class_init() * - TestIface5 is added in test_object_test_iface1_init() @@ -66,7 +66,7 @@ prefix ## _get_type (void) \ return object_type; \ } -#define DEFINE_IFACE(name, prefix, base_init) \ +#define DEFINE_IFACE(name, prefix, base_init, dflt_init) \ GType \ prefix ## _get_type (void) \ { \ @@ -79,6 +79,7 @@ prefix ## _get_type (void) \ sizeof (name ## Class), \ (GBaseInitFunc) base_init, \ (GBaseFinalizeFunc) NULL, \ + (GClassInitFunc) dflt_init, \ }; \ \ iface_type = g_type_register_static (G_TYPE_INTERFACE, \ @@ -98,6 +99,7 @@ struct _TestIfaceClass GTypeInterface base_iface; guint val; guint base_val; + guint default_val; }; #define TEST_TYPE_IFACE1 (test_iface1_get_type ()) @@ -105,9 +107,10 @@ struct _TestIfaceClass typedef struct _TestIface1 TestIface1; typedef struct _TestIfaceClass TestIface1Class; -static void test_iface1_base_init (TestIface1Class *iface); +static void test_iface1_base_init (TestIface1Class *iface); +static void test_iface1_default_init (TestIface1Class *iface, gpointer class_data); -static DEFINE_IFACE(TestIface1, test_iface1, test_iface1_base_init) +static DEFINE_IFACE(TestIface1, test_iface1, test_iface1_base_init, test_iface1_default_init) #define TEST_TYPE_IFACE2 (test_iface2_get_type ()) #define TEST_IFACE2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE2, TestIface2Class)) @@ -116,7 +119,7 @@ typedef struct _TestIfaceClass TestIface2Class; static void test_iface2_base_init (TestIface2Class *iface); -static DEFINE_IFACE(TestIface2, test_iface2, test_iface2_base_init) +static DEFINE_IFACE(TestIface2, test_iface2, test_iface2_base_init, NULL) #define TEST_TYPE_IFACE3 (test_iface3_get_type ()) #define TEST_IFACE3_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE3, TestIface3Class)) @@ -125,7 +128,7 @@ typedef struct _TestIfaceClass TestIface3Class; static void test_iface3_base_init (TestIface3Class *iface); -static DEFINE_IFACE(TestIface3, test_iface3, test_iface3_base_init) +static DEFINE_IFACE(TestIface3, test_iface3, test_iface3_base_init, NULL) #define TEST_TYPE_IFACE4 (test_iface4_get_type ()) #define TEST_IFACE4_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE4, TestIface4Class)) @@ -134,7 +137,7 @@ typedef struct _TestIfaceClass TestIface4Class; static void test_iface4_base_init (TestIface4Class *iface); -static DEFINE_IFACE(TestIface4, test_iface4, test_iface4_base_init) +static DEFINE_IFACE(TestIface4, test_iface4, test_iface4_base_init, NULL) #define TEST_TYPE_IFACE5 (test_iface5_get_type ()) #define TEST_IFACE5_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE5, TestIface5Class)) @@ -143,7 +146,7 @@ typedef struct _TestIfaceClass TestIface5Class; static void test_iface5_base_init (TestIface5Class *iface); -static DEFINE_IFACE(TestIface5, test_iface5, test_iface5_base_init) +static DEFINE_IFACE(TestIface5, test_iface5, test_iface5_base_init, NULL) #define TEST_TYPE_IFACE6 (test_iface6_get_type ()) #define TEST_IFACE6_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE6, TestIface6Class)) @@ -152,7 +155,7 @@ typedef struct _TestIfaceClass TestIface6Class; static void test_iface6_base_init (TestIface6Class *iface); -static DEFINE_IFACE(TestIface6, test_iface6, test_iface6_base_init) +static DEFINE_IFACE(TestIface6, test_iface6, test_iface6_base_init, NULL) /* * BaseObject, a parent class for TestObject @@ -187,9 +190,20 @@ struct _TestObjectClass }; #define TEST_CALLED_ONCE() G_STMT_START { \ - static gboolean called = FALSE; \ - g_assert (!called); \ - called = TRUE; \ + static gboolean called = 0; \ + g_assert (!called); \ + called = TRUE; \ +} G_STMT_END + +#define CHECK_IFACE_TWICE(iface) G_STMT_START { \ + static guint n_calls = 0; \ + n_calls++; \ + g_assert (n_calls <= 2); \ + g_assert (G_TYPE_IS_INTERFACE (((GTypeInterface*) iface)->g_type)); \ + if (n_calls == 1) \ + g_assert (((GTypeInterface*) iface)->g_instance_type == 0); \ + else \ + g_assert (G_TYPE_IS_OBJECT (((GTypeInterface*) iface)->g_instance_type)); \ } G_STMT_END #define ADD_IFACE(n) G_STMT_START { \ @@ -219,12 +233,15 @@ static void test_object_test_iface1_init (TestIface1Class *iface) { TEST_CALLED_ONCE(); - + + g_assert (iface->default_val == 0x111111); + iface->val = 0x10001; ADD_IFACE(5); iface1 = TRUE; + g_print ("interface1 object initializer\n"); } static void @@ -278,21 +295,48 @@ test_object_test_iface6_init (TestIface6Class *iface) } static void -test_iface1_base_init (TestIface1Class *iface) +test_iface1_default_init (TestIface1Class *iface, + gpointer class_data) { TEST_CALLED_ONCE(); + g_assert (iface->base_iface.g_type == TEST_TYPE_IFACE1); + g_assert (iface->base_iface.g_instance_type == 0); + g_assert (iface->base_val == 0x110011); + g_assert (iface->val == 0); + g_assert (iface->default_val == 0); + iface->default_val = 0x111111; + g_print ("interface1 default initializer\n"); +} - iface->base_val = 0x110011; - - ADD_IFACE(3); +static void +test_iface1_base_init (TestIface1Class *iface) +{ + static guint n_calls = 0; + n_calls++; + g_assert (n_calls <= 2); + + if (n_calls == 1) + { + iface->base_val = 0x110011; + g_assert (iface->default_val == 0); + } + else + { + g_assert (iface->base_val == 0x110011); + g_assert (iface->default_val == 0x111111); + } + + if (n_calls == 1) + ADD_IFACE(3); base1 = TRUE; + g_print ("interface1 base initializer\n"); } static void test_iface2_base_init (TestIface2Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x220022; @@ -302,7 +346,7 @@ test_iface2_base_init (TestIface2Class *iface) static void test_iface3_base_init (TestIface3Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x330033; @@ -312,7 +356,7 @@ test_iface3_base_init (TestIface3Class *iface) static void test_iface4_base_init (TestIface4Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x440044; @@ -322,7 +366,7 @@ test_iface4_base_init (TestIface4Class *iface) static void test_iface5_base_init (TestIface5Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x550055; @@ -332,7 +376,7 @@ test_iface5_base_init (TestIface5Class *iface) static void test_iface6_base_init (TestIface6Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x660066; @@ -424,5 +468,7 @@ main (int argc, iface = TEST_IFACE6_GET_CLASS (object); g_assert (iface && iface->val == 0x60006 && iface->base_val == 0x660066); + g_print ("testifaceinit: all done.\n"); + return 0; } diff --git a/tests/gobject/ifaceinit.c b/tests/gobject/ifaceinit.c index 94154ce1e..c25bb2968 100644 --- a/tests/gobject/ifaceinit.c +++ b/tests/gobject/ifaceinit.c @@ -28,7 +28,7 @@ * The test defines 5 interfaces: * * - TestIface1 is added before the class is initialized - * - TestIface2 is added in base_object_baes_init() + * - TestIface2 is added in base_object_base_init() * - TestIface3 is added in test_iface1_base_init() * - TestIface4 is added in test_object_class_init() * - TestIface5 is added in test_object_test_iface1_init() @@ -66,7 +66,7 @@ prefix ## _get_type (void) \ return object_type; \ } -#define DEFINE_IFACE(name, prefix, base_init) \ +#define DEFINE_IFACE(name, prefix, base_init, dflt_init) \ GType \ prefix ## _get_type (void) \ { \ @@ -79,6 +79,7 @@ prefix ## _get_type (void) \ sizeof (name ## Class), \ (GBaseInitFunc) base_init, \ (GBaseFinalizeFunc) NULL, \ + (GClassInitFunc) dflt_init, \ }; \ \ iface_type = g_type_register_static (G_TYPE_INTERFACE, \ @@ -98,6 +99,7 @@ struct _TestIfaceClass GTypeInterface base_iface; guint val; guint base_val; + guint default_val; }; #define TEST_TYPE_IFACE1 (test_iface1_get_type ()) @@ -105,9 +107,10 @@ struct _TestIfaceClass typedef struct _TestIface1 TestIface1; typedef struct _TestIfaceClass TestIface1Class; -static void test_iface1_base_init (TestIface1Class *iface); +static void test_iface1_base_init (TestIface1Class *iface); +static void test_iface1_default_init (TestIface1Class *iface, gpointer class_data); -static DEFINE_IFACE(TestIface1, test_iface1, test_iface1_base_init) +static DEFINE_IFACE(TestIface1, test_iface1, test_iface1_base_init, test_iface1_default_init) #define TEST_TYPE_IFACE2 (test_iface2_get_type ()) #define TEST_IFACE2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE2, TestIface2Class)) @@ -116,7 +119,7 @@ typedef struct _TestIfaceClass TestIface2Class; static void test_iface2_base_init (TestIface2Class *iface); -static DEFINE_IFACE(TestIface2, test_iface2, test_iface2_base_init) +static DEFINE_IFACE(TestIface2, test_iface2, test_iface2_base_init, NULL) #define TEST_TYPE_IFACE3 (test_iface3_get_type ()) #define TEST_IFACE3_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE3, TestIface3Class)) @@ -125,7 +128,7 @@ typedef struct _TestIfaceClass TestIface3Class; static void test_iface3_base_init (TestIface3Class *iface); -static DEFINE_IFACE(TestIface3, test_iface3, test_iface3_base_init) +static DEFINE_IFACE(TestIface3, test_iface3, test_iface3_base_init, NULL) #define TEST_TYPE_IFACE4 (test_iface4_get_type ()) #define TEST_IFACE4_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE4, TestIface4Class)) @@ -134,7 +137,7 @@ typedef struct _TestIfaceClass TestIface4Class; static void test_iface4_base_init (TestIface4Class *iface); -static DEFINE_IFACE(TestIface4, test_iface4, test_iface4_base_init) +static DEFINE_IFACE(TestIface4, test_iface4, test_iface4_base_init, NULL) #define TEST_TYPE_IFACE5 (test_iface5_get_type ()) #define TEST_IFACE5_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE5, TestIface5Class)) @@ -143,7 +146,7 @@ typedef struct _TestIfaceClass TestIface5Class; static void test_iface5_base_init (TestIface5Class *iface); -static DEFINE_IFACE(TestIface5, test_iface5, test_iface5_base_init) +static DEFINE_IFACE(TestIface5, test_iface5, test_iface5_base_init, NULL) #define TEST_TYPE_IFACE6 (test_iface6_get_type ()) #define TEST_IFACE6_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE6, TestIface6Class)) @@ -152,7 +155,7 @@ typedef struct _TestIfaceClass TestIface6Class; static void test_iface6_base_init (TestIface6Class *iface); -static DEFINE_IFACE(TestIface6, test_iface6, test_iface6_base_init) +static DEFINE_IFACE(TestIface6, test_iface6, test_iface6_base_init, NULL) /* * BaseObject, a parent class for TestObject @@ -187,9 +190,20 @@ struct _TestObjectClass }; #define TEST_CALLED_ONCE() G_STMT_START { \ - static gboolean called = FALSE; \ - g_assert (!called); \ - called = TRUE; \ + static gboolean called = 0; \ + g_assert (!called); \ + called = TRUE; \ +} G_STMT_END + +#define CHECK_IFACE_TWICE(iface) G_STMT_START { \ + static guint n_calls = 0; \ + n_calls++; \ + g_assert (n_calls <= 2); \ + g_assert (G_TYPE_IS_INTERFACE (((GTypeInterface*) iface)->g_type)); \ + if (n_calls == 1) \ + g_assert (((GTypeInterface*) iface)->g_instance_type == 0); \ + else \ + g_assert (G_TYPE_IS_OBJECT (((GTypeInterface*) iface)->g_instance_type)); \ } G_STMT_END #define ADD_IFACE(n) G_STMT_START { \ @@ -219,12 +233,15 @@ static void test_object_test_iface1_init (TestIface1Class *iface) { TEST_CALLED_ONCE(); - + + g_assert (iface->default_val == 0x111111); + iface->val = 0x10001; ADD_IFACE(5); iface1 = TRUE; + g_print ("interface1 object initializer\n"); } static void @@ -278,21 +295,48 @@ test_object_test_iface6_init (TestIface6Class *iface) } static void -test_iface1_base_init (TestIface1Class *iface) +test_iface1_default_init (TestIface1Class *iface, + gpointer class_data) { TEST_CALLED_ONCE(); + g_assert (iface->base_iface.g_type == TEST_TYPE_IFACE1); + g_assert (iface->base_iface.g_instance_type == 0); + g_assert (iface->base_val == 0x110011); + g_assert (iface->val == 0); + g_assert (iface->default_val == 0); + iface->default_val = 0x111111; + g_print ("interface1 default initializer\n"); +} - iface->base_val = 0x110011; - - ADD_IFACE(3); +static void +test_iface1_base_init (TestIface1Class *iface) +{ + static guint n_calls = 0; + n_calls++; + g_assert (n_calls <= 2); + + if (n_calls == 1) + { + iface->base_val = 0x110011; + g_assert (iface->default_val == 0); + } + else + { + g_assert (iface->base_val == 0x110011); + g_assert (iface->default_val == 0x111111); + } + + if (n_calls == 1) + ADD_IFACE(3); base1 = TRUE; + g_print ("interface1 base initializer\n"); } static void test_iface2_base_init (TestIface2Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x220022; @@ -302,7 +346,7 @@ test_iface2_base_init (TestIface2Class *iface) static void test_iface3_base_init (TestIface3Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x330033; @@ -312,7 +356,7 @@ test_iface3_base_init (TestIface3Class *iface) static void test_iface4_base_init (TestIface4Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x440044; @@ -322,7 +366,7 @@ test_iface4_base_init (TestIface4Class *iface) static void test_iface5_base_init (TestIface5Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x550055; @@ -332,7 +376,7 @@ test_iface5_base_init (TestIface5Class *iface) static void test_iface6_base_init (TestIface6Class *iface) { - TEST_CALLED_ONCE(); + CHECK_IFACE_TWICE (iface); iface->base_val = 0x660066; @@ -424,5 +468,7 @@ main (int argc, iface = TEST_IFACE6_GET_CLASS (object); g_assert (iface && iface->val == 0x60006 && iface->base_val == 0x660066); + g_print ("testifaceinit: all done.\n"); + return 0; }