diff --git a/ChangeLog b/ChangeLog index 1c9d80784..f63874a71 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 1c9d80784..f63874a71 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,9 +1,7 @@ -2001-09-10 Alex Larsson +Mon Sep 10 17:13:36 2001 Tim Janik - * gobject/gboxed.[ch]: - * gobject/gsourceclosure.c: - Removed is_refcounted and GBoxedInitFunc from - g_boxed_type_register_static(). + * glib/gmessages.h: got rid of g_set_error_handler(), + g_set_warning_handler(), g_set_message_handler(). Mon Sep 10 11:42:58 2001 Owen Taylor diff --git a/docs/Changes-2.0.txt b/docs/Changes-2.0.txt index 28b888977..e670ea4d8 100644 --- a/docs/Changes-2.0.txt +++ b/docs/Changes-2.0.txt @@ -40,3 +40,8 @@ @max_tokens + 1 Code depending on either of these bugs will need to be fixed. + +* deprecated functions that got removed: + g_set_error_handler(), g_set_warning_handler(), + g_set_message_handler(), use g_log_set_handler() instead. + diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index f1e00a2dc..6e3102fbf 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +Wed Sep 5 05:24:07 2001 Tim Janik + + * gobject/tmpl/gboxed.sgml: documented some functions. + + * gobject/tmpl/objects.sgml: some fixups. + Mon Sep 10 11:37:02 2001 Owen Taylor * glib/glib-sections.txt: Update. diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 441bbd407..3350d6f91 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -777,14 +777,6 @@ g_log_set_always_fatal g_log_set_fatal_mask g_log_default_handler - -g_set_error_handler -GErrorFunc -g_set_warning_handler -GWarningFunc -g_set_message_handler - -
Timers timers diff --git a/docs/reference/glib/tmpl/glib-unused.sgml b/docs/reference/glib/tmpl/glib-unused.sgml index 3a95820ba..13142945b 100644 --- a/docs/reference/glib/tmpl/glib-unused.sgml +++ b/docs/reference/glib/tmpl/glib-unused.sgml @@ -1,3 +1,29 @@ + + +These functions provide support for logging error messages or messages +used for debugging. + + + +There are several built-in levels of messages, defined in #GLogLevelFlags. +These can be extended with user-defined levels. + + + + + + + + + + +versatile support for logging messages with different levels of importance. + + + +Message Logging + + @@ -51,6 +77,13 @@ @s2: @Returns: + + +Specifies the type of function passed to g_set_error_handler(). + + +@str: the error message. + @@ -71,6 +104,13 @@ @G_IO_FILE_MODE_READ_WRITE_TRUNCATE: @G_IO_FILE_MODE_READ_WRITE_APPEND: + + +Specifies the type of function passed to g_set_warning_handler(). + + +@str: the warning message. + @@ -223,6 +263,33 @@ documentation. @filename: the file name. @Returns: the file attributes. + + +Sets the function to be called to handle error messages. +This function is deprecated in favour of the new logging facilities. + + +@func: the function to be called to handle error messages. +@Returns: the old error handler. + + + +Sets the function to be called to handle messages. +This function is deprecated in favour of the new logging facilities. + + +@func: the function to be called to handle normal messages. +@Returns: the old message handler. + + + +Sets the function to be called to handle warning messages. +This function is deprecated in favour of the new logging facilities. + + +@func: the function to be called to handle warning messages. +@Returns: the old warning handler. + diff --git a/docs/reference/glib/tmpl/messages.sgml b/docs/reference/glib/tmpl/messages.sgml index f88fb80b3..8ebe23e1c 100644 --- a/docs/reference/glib/tmpl/messages.sgml +++ b/docs/reference/glib/tmpl/messages.sgml @@ -242,49 +242,3 @@ stderr is used for levels %G_LOG_LEVEL_ERROR, %G_LOG_LEVEL_CRITICAL, and @unused_data: data passed from g_log which is unused. - - -Sets the function to be called to handle error messages. -This function is deprecated in favour of the new logging facilities. - - -@func: the function to be called to handle error messages. -@Returns: the old error handler. - - - - -Specifies the type of function passed to g_set_error_handler(). - - -@str: the error message. - - - - -Sets the function to be called to handle warning messages. -This function is deprecated in favour of the new logging facilities. - - -@func: the function to be called to handle warning messages. -@Returns: the old warning handler. - - - - -Specifies the type of function passed to g_set_warning_handler(). - - -@str: the warning message. - - - - -Sets the function to be called to handle messages. -This function is deprecated in favour of the new logging facilities. - - -@func: the function to be called to handle normal messages. -@Returns: the old message handler. - - diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 621aa75ad..6567f4533 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -234,6 +234,7 @@ g_flags_complete_type_info gboxed Boxed Types GBoxed +GBoxedInitFunc GBoxedCopyFunc GBoxedFreeFunc g_boxed_copy diff --git a/docs/reference/gobject/tmpl/enumerations_flags.sgml b/docs/reference/gobject/tmpl/enumerations_flags.sgml index c72b7d3fb..8c91f7908 100644 --- a/docs/reference/gobject/tmpl/enumerations_flags.sgml +++ b/docs/reference/gobject/tmpl/enumerations_flags.sgml @@ -1,12 +1,11 @@ -Enumeration and Flag Types +Enums and Flags - +Enumeration and flags types. - diff --git a/docs/reference/gobject/tmpl/gboxed.sgml b/docs/reference/gobject/tmpl/gboxed.sgml index 87183cbca..1e6b2882b 100644 --- a/docs/reference/gobject/tmpl/gboxed.sgml +++ b/docs/reference/gobject/tmpl/gboxed.sgml @@ -1,8 +1,8 @@ -gboxed +GBoxed - +Mechanism to wrap opaque C structures registered by the type system. @@ -11,52 +11,55 @@ gboxed - +#GParamSpecBoxed, g_param_spec_boxed() - +This function is provided by the user and should produce a copy of the passed +in boxed structure. -@boxed: -@Returns: +@boxed: The boxed structure to be copied. +@Returns: The newly created copy of the boxed structure. - +This function is provided by the user and should free the boxed +structure passed. -@boxed: +@boxed: The boxed structure to be freed. - +Provide a copy of a boxed structure @src_boxed which is of type @boxed_type. -@boxed_type: -@src_boxed: -@Returns: +@boxed_type: The type of @src_boxed. +@src_boxed: The boxed structure to be copied. +@Returns: The newly created copy of the boxed structure. - +Free the boxed structure @boxed which is of type @boxed_type. -@boxed_type: -@boxed: +@boxed_type: The type of @boxed. +@boxed: The boxed structure to be freed. - +Assign a #GValue which is initialized with a certain boxed type a +boxed structure of that very same type. -@value: -@boxed: +@value: The #GValue to be assigned a value to. +@boxed: The boxed structure which has to be of the same type the #GValue got initialized with. @@ -97,14 +100,17 @@ This is an internal function introduced mainly for C marshallers. - +This function creates a new %G_TYPE_BOXED derived type id for a new +boxed type with name @name. Boxed type handling functions have to be +provided to copy and free opaque boxed structures of this type. -@name: +@name: Name of the new boxed type. +@boxed_copy: Boxed structure copy function. +@boxed_free: Boxed structure free function. +@Returns: New %G_TYPE_BOXED derived type id for @name. + @boxed_init: -@boxed_copy: -@boxed_free: @is_refcounted: -@Returns: diff --git a/docs/reference/gobject/tmpl/gobject-unused.sgml b/docs/reference/gobject/tmpl/gobject-unused.sgml index 01359274a..7181f37bf 100644 --- a/docs/reference/gobject/tmpl/gobject-unused.sgml +++ b/docs/reference/gobject/tmpl/gobject-unused.sgml @@ -4,6 +4,13 @@ + + + + + +@Returns: + diff --git a/docs/reference/gobject/tmpl/objects.sgml b/docs/reference/gobject/tmpl/objects.sgml index bcd3eefb3..904910f09 100644 --- a/docs/reference/gobject/tmpl/objects.sgml +++ b/docs/reference/gobject/tmpl/objects.sgml @@ -1,8 +1,8 @@ -The Base Object Type +GObject - +The base object type. @@ -16,7 +16,8 @@ The Base Object Type - +All the fields in the GObject structure are private to the #GObject implementation +and should never be accessed directly. @g_type_instance: @@ -71,26 +72,30 @@ The Base Object Type - +Return a boolean value of %FALSE or %TRUE indicating whether +the passed in type id is a %G_TYPE_OBJECT or derived from it. -@type: +@type: Type id to check for is a %G_TYPE_OBJECT relationship. +@Returns: %FALSE or %TRUE, indicating whether @type is a %G_TYPE_OBJECT. - +Cast a #GObject or derived pointer into a (GObject*) pointer. +Depending on the current debugging level, this function may invoke +certain runtime checks to identify invalid casts. -@object: +@object: Object which is subject to casting. - +Check whether a valid #GTypeInstance pointer is of type %G_TYPE_OBJECT. -@object: +@object: Instance to check for being a %G_TYPE_OBJECT. @@ -119,10 +124,11 @@ The Base Object Type - +Return the type id of an object. -@object: +@object: Object to return the type id for. +@Returns: Type id of @object. @@ -256,8 +262,8 @@ lifetime of @object. When the @object is finalized, @weak_pointer will be set to %NULL. -@object: the object that should be weak referenced. -@weak_pointer_location: the memory address of a pointer. +@object: The object that should be weak referenced. +@weak_pointer_location: The memory address of a pointer. @@ -267,8 +273,8 @@ using g_object_add_weak_pointer(). The @weak_pointer_location has to match the one used with g_object_add_weak_pointer(). -@object: the object that is weak referenced. -@weak_pointer_location: the memory address of a pointer. +@object: The object that is weak referenced. +@weak_pointer_location: The memory address of a pointer. @@ -302,8 +308,6 @@ to match the one used with g_object_add_weak_pointer(). @first_property_name: @Varargs: @Returns: - -@first_param_name: @@ -314,8 +318,6 @@ to match the one used with g_object_add_weak_pointer(). @object: @first_property_name: @Varargs: - -@first_param_name: @@ -454,8 +456,6 @@ to match the one used with g_object_add_weak_pointer(). @first_property_name: @var_args: @Returns: - -@first_param_name: @@ -466,8 +466,6 @@ to match the one used with g_object_add_weak_pointer(). @object: @first_property_name: @var_args: - -@first_param_name: @@ -478,8 +476,6 @@ to match the one used with g_object_add_weak_pointer(). @object: @first_property_name: @var_args: - -@first_param_name: diff --git a/docs/reference/gobject/tmpl/value_arrays.sgml b/docs/reference/gobject/tmpl/value_arrays.sgml index 1c77eaaef..a1d9f8d0d 100644 --- a/docs/reference/gobject/tmpl/value_arrays.sgml +++ b/docs/reference/gobject/tmpl/value_arrays.sgml @@ -13,7 +13,7 @@ in order for it to be used as a boxed type through %G_TYPE_VALUE_ARRAY. -#GValue, #GParamSpecValueArray +#GValue, #GParamSpecValueArray, g_param_spec_value_array() diff --git a/glib/giochannel.h b/glib/giochannel.h index be6b8aac8..89b327d8a 100644 --- a/glib/giochannel.h +++ b/glib/giochannel.h @@ -98,7 +98,7 @@ typedef enum G_IO_FLAG_IS_SEEKABLE = 1 << 4, /* Read only flag */ G_IO_FLAG_MASK = (1 << 5) - 1, G_IO_FLAG_GET_MASK = G_IO_FLAG_MASK, - G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK, + G_IO_FLAG_SET_MASK = G_IO_FLAG_APPEND | G_IO_FLAG_NONBLOCK } GIOFlags; struct _GIOChannel diff --git a/glib/gmessages.c b/glib/gmessages.c index 11d0c34e7..5c761798e 100644 --- a/glib/gmessages.c +++ b/glib/gmessages.c @@ -85,9 +85,6 @@ static GLogDomain *g_log_domains = NULL; static GLogLevelFlags g_log_always_fatal = G_LOG_FATAL_MASK; static GPrintFunc glib_print_func = NULL; static GPrintFunc glib_printerr_func = NULL; -static GErrorFunc glib_error_func = NULL; -static GWarningFunc glib_warning_func = NULL; -static GPrintFunc glib_message_func = NULL; static GPrivate* g_log_depth = NULL; @@ -581,9 +578,6 @@ g_log_default_handler (const gchar *log_domain, GFileDescriptor fd; gboolean in_recursion; gboolean is_fatal; - GErrorFunc local_glib_error_func; - GWarningFunc local_glib_warning_func; - GPrintFunc local_glib_message_func; in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0; is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0; @@ -602,21 +596,9 @@ g_log_default_handler (const gchar *log_domain, fd = (log_level > G_LOG_LEVEL_MESSAGE) ? 1 : 2; #endif - g_mutex_lock (g_messages_lock); - local_glib_error_func = glib_error_func; - local_glib_warning_func = glib_warning_func; - local_glib_message_func = glib_message_func; - g_mutex_unlock (g_messages_lock); - switch (log_level) { case G_LOG_LEVEL_ERROR: - if (!log_domain && local_glib_error_func) - { - /* compatibility code */ - local_glib_error_func (message); - return; - } /* use write(2) for output, in case we are out of memeory */ ensure_stdout_valid (); write (fd, "\n", 1); @@ -662,12 +644,6 @@ g_log_default_handler (const gchar *log_domain, write (fd, "\n", 1); break; case G_LOG_LEVEL_WARNING: - if (!log_domain && local_glib_warning_func) - { - /* compatibility code */ - local_glib_warning_func (message); - return; - } ensure_stdout_valid (); write (fd, "\n", 1); g_log_write_prefix (fd, log_level); @@ -690,12 +666,6 @@ g_log_default_handler (const gchar *log_domain, write (fd, "\n", 1); break; case G_LOG_LEVEL_MESSAGE: - if (!log_domain && local_glib_message_func) - { - /* compatibility code */ - local_glib_message_func (message); - return; - } ensure_stdout_valid (); g_log_write_prefix (fd, log_level); @@ -884,48 +854,6 @@ g_printerr (const gchar *format, g_free (string); } -/* compatibility code */ -GErrorFunc -g_set_error_handler (GErrorFunc func) -{ - GErrorFunc old_error_func; - - g_mutex_lock (g_messages_lock); - old_error_func = glib_error_func; - glib_error_func = func; - g_mutex_unlock (g_messages_lock); - - return old_error_func; -} - -/* compatibility code */ -GWarningFunc -g_set_warning_handler (GWarningFunc func) -{ - GWarningFunc old_warning_func; - - g_mutex_lock (g_messages_lock); - old_warning_func = glib_warning_func; - glib_warning_func = func; - g_mutex_unlock (g_messages_lock); - - return old_warning_func; -} - -/* compatibility code */ -GPrintFunc -g_set_message_handler (GPrintFunc func) -{ - GPrintFunc old_message_func; - - g_mutex_lock (g_messages_lock); - old_message_func = glib_message_func; - glib_message_func = func; - g_mutex_unlock (g_messages_lock); - - return old_message_func; -} - #ifndef MB_LEN_MAX # define MB_LEN_MAX 8 #endif diff --git a/glib/gmessages.h b/glib/gmessages.h index beedda5b3..9fc556fa7 100644 --- a/glib/gmessages.h +++ b/glib/gmessages.h @@ -170,12 +170,6 @@ void g_printerr (const gchar *format, ...) G_GNUC_PRINTF (1, 2); GPrintFunc g_set_printerr_handler (GPrintFunc func); -/* deprecated compatibility functions, use g_log_set_handler() instead */ -typedef void (*GErrorFunc) (const gchar *str); -typedef void (*GWarningFunc) (const gchar *str); -GErrorFunc g_set_error_handler (GErrorFunc func); -GWarningFunc g_set_warning_handler (GWarningFunc func); -GPrintFunc g_set_message_handler (GPrintFunc func); /* Provide macros for error handling. The "assert" macros will * exit on failure. The "return" macros will exit the current diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 8e1fc008d..0b0e39734 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,22 @@ +Mon Sep 10 19:27:47 2001 Tim Janik + + * gtype.[hc]: + g_type_add_interface*(): implement the ability to add an interface to + a type whose parents already conform to this interface. + such "overriding" interfaces, when initialized, are not just initialized + with 0, but with a copy of the interface they override. + g_type_interface_peek_parent(): new function, return the interface + that this interface "overrides", if any. + + * testgruntime.c: test new interface stuff. + +2001-09-10 Alex Larsson + + * gobject/gboxed.[ch]: + * gobject/gsourceclosure.c: + Removed is_refcounted and GBoxedInitFunc from + g_boxed_type_register_static(). + Sat Sep 8 14:13:57 2001 Owen Taylor * gobject/Makefile.am: Move gbsearcharray.[ch] to glib diff --git a/gobject/gtype.c b/gobject/gtype.c index 5df44e73c..af4fc46e3 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -132,6 +132,8 @@ static inline gpointer type_get_qdata_L (TypeNode *node, static inline void type_set_qdata_W (TypeNode *node, GQuark quark, gpointer data); +static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface, + GType instance_type); /* --- structures --- */ @@ -333,10 +335,14 @@ type_node_any_new_W (TypeNode *pnode, } else { + guint j; + CLASSED_NODE_N_IFACES (node) = CLASSED_NODE_N_IFACES (pnode); CLASSED_NODE_IFACES_ENTRIES (node) = g_memdup (CLASSED_NODE_IFACES_ENTRIES (pnode), sizeof (CLASSED_NODE_IFACES_ENTRIES (pnode)[0]) * CLASSED_NODE_N_IFACES (node)); + for (j = 0; j < CLASSED_NODE_N_IFACES (node); j++) + CLASSED_NODE_IFACES_ENTRIES (node)[j].vtable = NULL; } i = pnode->n_children++; @@ -778,8 +784,8 @@ check_type_info_L (TypeNode *pnode, } static TypeNode* -find_conforming_type_L (TypeNode *pnode, - TypeNode *iface) +find_conforming_child_type_L (TypeNode *pnode, + TypeNode *iface) { TypeNode *node = NULL; guint i; @@ -788,7 +794,7 @@ find_conforming_type_L (TypeNode *pnode, return pnode; for (i = 0; i < pnode->n_children && !node; i++) - node = find_conforming_type_L (lookup_type_node_L (pnode->children[i]), iface); + node = find_conforming_child_type_L (lookup_type_node_L (pnode->children[i]), iface); return node; } @@ -799,6 +805,7 @@ check_add_interface_L (GType instance_type, { TypeNode *node = lookup_type_node_L (instance_type); TypeNode *iface = lookup_type_node_L (iface_type); + IFaceEntry *entry; TypeNode *tnode; if (!node || !node->is_instantiatable) @@ -824,7 +831,20 @@ check_add_interface_L (GType instance_type, NODE_NAME (tnode)); return FALSE; } - tnode = find_conforming_type_L (node, iface); // FIXME: iface overriding + /* allow overriding of interface type introduced for parent type */ + entry = type_lookup_iface_entry_L (node, iface); + if (entry && entry->vtable == NULL && !type_iface_peek_holder_L (iface, NODE_TYPE (node))) + { + /* ok, we do conform to this interface already, but the interface vtable was not + * yet intialized, and we just conform to the interface because it got added to + * one of our parents. so we allow overriding of holder info here. + */ + return TRUE; + } + /* check whether one of our children already conforms (or whether the interface + * got added to this node already) + */ + tnode = find_conforming_child_type_L (node, iface); /* tnode is_a node */ if (tnode) { g_warning ("cannot add interface type `%s' to type `%s', since type `%s' already conforms to interface", @@ -1044,9 +1064,12 @@ type_node_add_iface_entry_W (TypeNode *node, for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (entries[i].iface_type == iface_type) { - g_warning ("failed to add interface, type `%s' already conforms to interface type `%s'", - type_descriptive_name_L (NODE_TYPE (node)), - type_descriptive_name_L (iface_type)); + /* this can (should) only happen if our parent type already conformed + * to iface_type and node got it's own holder info. here, our + * children should already have entries with NULL vtables, so + * we're actually done. + */ + g_assert (entries[i].vtable == NULL); return; } else if (entries[i].iface_type > iface_type) @@ -1206,17 +1229,27 @@ g_type_interface_add_prerequisite (GType interface_type, } static IFaceHolder* -type_iface_retrive_holder_info_Wm (TypeNode *iface, - GType instance_type) +type_iface_peek_holder_L (TypeNode *iface, + GType instance_type) { - IFaceHolder *iholder = iface_node_get_holders_L (iface); - + IFaceHolder *iholder; + g_assert (NODE_IS_IFACE (iface)); - - while (iholder->instance_type != instance_type) + + iholder = iface_node_get_holders_L (iface); + while (iholder && iholder->instance_type != instance_type) iholder = iholder->next; - - if (!iholder->info) + return iholder; +} + +static IFaceHolder* +type_iface_retrive_holder_info_Wm (TypeNode *iface, + GType instance_type, + gboolean need_info) +{ + IFaceHolder *iholder = type_iface_peek_holder_L (iface, instance_type); + + if (iholder && !iholder->info && need_info) { GInterfaceInfo tmp_info; @@ -1239,7 +1272,7 @@ type_iface_retrive_holder_info_Wm (TypeNode *iface, iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); } - return iholder; + return iholder; /* we don't modify write lock upon returning NULL */ } static void @@ -1372,37 +1405,33 @@ g_type_free_instance (GTypeInstance *instance) g_type_class_unref (class); } -static void -type_propagate_iface_vtable_W (TypeNode *pnode, - TypeNode *iface, - GTypeInterface *vtable) -{ - IFaceEntry *entry = type_lookup_iface_entry_L (pnode, iface); - guint i; - - entry->vtable = vtable; - for (i = 0; i < pnode->n_children; i++) - { - TypeNode *node = lookup_type_node_L (pnode->children[i]); - - type_propagate_iface_vtable_W (node, iface, vtable); - } -} - -static void +static gboolean type_iface_vtable_init_Wm (TypeNode *iface, TypeNode *node) { -#ifndef G_DISABLE_ASSERT IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); -#endif - IFaceHolder *iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node)); - GTypeInterface *vtable; + IFaceHolder *iholder; + GTypeInterface *vtable = NULL; + TypeNode *pnode; + + /* type_iface_retrive_holder_info_Wm() doesn't modify write lock for returning NULL */ + iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node), TRUE); + if (!iholder) + return FALSE; /* we don't modify write lock upon FALSE */ g_assert (iface->data && entry && entry->vtable == NULL && iholder && iholder->info); - vtable = g_malloc0 (iface->data->iface.vtable_size); - type_propagate_iface_vtable_W (node, iface, vtable); + pnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); + if (pnode) /* want to copy over parent iface contents */ + { + IFaceEntry *pentry = type_lookup_iface_entry_L (pnode, iface); + + if (pentry) + vtable = g_memdup (pentry->vtable, iface->data->iface.vtable_size); + } + if (!vtable) + vtable = g_malloc0 (iface->data->iface.vtable_size); + entry->vtable = vtable; vtable->g_type = NODE_TYPE (iface); vtable->g_instance_type = NODE_TYPE (node); @@ -1415,25 +1444,25 @@ type_iface_vtable_init_Wm (TypeNode *iface, iholder->info->interface_init (vtable, iholder->info->interface_data); G_WRITE_LOCK (&type_rw_lock); } + return TRUE; /* write lock modified */ } -static void +static gboolean type_iface_vtable_finalize_Wm (TypeNode *iface, TypeNode *node, GTypeInterface *vtable) { -#ifndef G_DISABLE_ASSERT IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); -#endif - IFaceHolder *iholder = iface_node_get_holders_L (iface); + IFaceHolder *iholder; + + /* type_iface_retrive_holder_info_Wm() doesn't modify write lock for returning NULL */ + iholder = type_iface_retrive_holder_info_Wm (iface, NODE_TYPE (node), FALSE); + if (!iholder) + return FALSE; /* we don't modify write lock upon FALSE */ - g_assert (entry && entry->vtable == vtable); + g_assert (entry && entry->vtable == vtable && iholder->info); - while (iholder->instance_type != NODE_TYPE (node)) - iholder = iholder->next; - g_assert (iholder && iholder->info); - - type_propagate_iface_vtable_W (node, iface, NULL); + entry->vtable = NULL; if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base) { G_WRITE_UNLOCK (&type_rw_lock); @@ -1448,6 +1477,8 @@ type_iface_vtable_finalize_Wm (TypeNode *iface, g_free (vtable); type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node)); + + return TRUE; /* write lock modified */ } static void @@ -1457,7 +1488,7 @@ type_class_init_Wm (TypeNode *node, GSList *slist, *init_slist = NULL; GTypeClass *class; IFaceEntry *entry; - TypeNode *bnode; + TypeNode *bnode, *pnode; guint i; g_assert (node->is_classed && node->data && @@ -1498,14 +1529,38 @@ type_class_init_Wm (TypeNode *node, G_WRITE_LOCK (&type_rw_lock); - /* ok, we got the class done, now initialize all interfaces */ - for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) - if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable) - entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; + /* ok, we got the class done, now initialize all interfaces, either + * from parent, or through our holder info + */ + pnode = lookup_type_node_L (NODE_PARENT_TYPE (node)); + entry = CLASSED_NODE_IFACES_ENTRIES (node) + 0; while (entry) { - type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node); + g_assert (entry->vtable == NULL); + if (!type_iface_vtable_init_Wm (lookup_type_node_L (entry->iface_type), node)) + { + guint j; + + /* type_iface_vtable_init_Wm() doesn't modify write lock upon FALSE, + * need to get this interface from parent + */ + g_assert (pnode != NULL); + + for (j = 0; j < CLASSED_NODE_N_IFACES (pnode); j++) + { + IFaceEntry *pentry = CLASSED_NODE_IFACES_ENTRIES (pnode) + j; + + if (pentry->iface_type == entry->iface_type) + { + entry->vtable = pentry->vtable; + break; + } + } + g_assert (entry->vtable != NULL); + } + + /* refetch entry, IFACES_ENTRIES might be modified */ for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (!CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable) entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; @@ -1530,8 +1585,15 @@ type_data_finalize_class_ifaces_Wm (TypeNode *node) entry = CLASSED_NODE_IFACES_ENTRIES (node) + i; while (entry) { - type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable); + if (!type_iface_vtable_finalize_Wm (lookup_type_node_L (entry->iface_type), node, entry->vtable)) + { + /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE, + * iface vtable came from parent + */ + entry->vtable = NULL; + } + /* refetch entry, IFACES_ENTRIES might be modified */ for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++) if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable && CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node)) @@ -1835,7 +1897,14 @@ g_type_add_interface_static (GType instance_type, TypeNode *iface = lookup_type_node_L (interface_type); if (check_interface_info_L (iface, NODE_TYPE (node), info)) - type_add_interface_W (node, iface, info, NULL); + { + type_add_interface_W (node, iface, info, NULL); + /* if we have a class already, the interface vtable needs to + * be initialized as well + */ + if (node->data && node->data->class.class) + type_iface_vtable_init_Wm (iface, node); + } } G_WRITE_UNLOCK (&type_rw_lock); } @@ -1863,6 +1932,11 @@ g_type_add_interface_dynamic (GType instance_type, TypeNode *iface = lookup_type_node_L (interface_type); type_add_interface_W (node, iface, NULL, plugin); + /* if we have a class already, the interface vtable needs to + * be initialized as well + */ + if (node->data && node->data->class.class) + type_iface_vtable_init_Wm (iface, node); } G_WRITE_UNLOCK (&type_rw_lock); } @@ -1978,7 +2052,7 @@ gpointer g_type_class_peek_parent (gpointer g_class) { TypeNode *node; - gpointer class; + gpointer class = NULL; g_return_val_if_fail (g_class != NULL, NULL); @@ -1989,8 +2063,8 @@ g_type_class_peek_parent (gpointer g_class) node = lookup_type_node_L (NODE_PARENT_TYPE (node)); class = node->data->class.class; } - else - class = NULL; + else if (NODE_PARENT_TYPE (node)) + g_warning (G_STRLOC ": invalid class pointer `%p'", g_class); G_READ_UNLOCK (&type_rw_lock); return class; @@ -2017,11 +2091,42 @@ g_type_interface_peek (gpointer instance_class, if (entry && entry->vtable) vtable = entry->vtable; } + else + g_warning (G_STRLOC ": invalid class pointer `%p'", class); G_READ_UNLOCK (&type_rw_lock); return vtable; } +gpointer +g_type_interface_peek_parent (gpointer g_iface) +{ + TypeNode *node; + TypeNode *iface; + gpointer vtable = NULL; + GTypeInterface *iface_class = g_iface; + + g_return_val_if_fail (g_iface != NULL, NULL); + + G_READ_LOCK (&type_rw_lock); + iface = lookup_type_node_L (iface_class->g_type); + node = lookup_type_node_L (iface_class->g_instance_type); + if (node) + node = lookup_type_node_L (NODE_PARENT_TYPE (node)); + if (node && node->is_instantiatable && iface) + { + IFaceEntry *entry = type_lookup_iface_entry_L (node, iface); + + if (entry && entry->vtable) + vtable = entry->vtable; + } + else if (node) + g_warning (G_STRLOC ": invalid interface pointer `%p'", g_iface); + G_READ_UNLOCK (&type_rw_lock); + + return vtable; +} + G_CONST_RETURN gchar* g_type_name (GType type) { diff --git a/gobject/gtype.h b/gobject/gtype.h index 5ae806d7c..64f82851b 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -200,6 +200,7 @@ void g_type_class_unref (gpointer g_class); gpointer g_type_class_peek_parent (gpointer g_class); gpointer g_type_interface_peek (gpointer instance_class, GType iface_type); +gpointer g_type_interface_peek_parent (gpointer g_iface); /* g_free() the returned arrays */ GType* g_type_children (GType type, diff --git a/gobject/testgobject.c b/gobject/testgobject.c index ef8a755d5..e7d5216ce 100644 --- a/gobject/testgobject.c +++ b/gobject/testgobject.c @@ -20,28 +20,24 @@ #define G_LOG_DOMAIN "TestObject" #include -#define TEST_TYPE_OBJECT (test_object_get_type ()) -#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) -#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) -#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) -#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) -#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) - -typedef struct _TestIface TestIface; -typedef struct -{ - GTypeInterface base_iface; -} TestIfaceClass; -typedef struct -{ - GObject parent_instance; -} TestObject; +/* --- TestIface --- */ #define TEST_TYPE_IFACE (test_iface_get_type ()) #define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface)) #define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE)) -#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TEST_TYPE_IFACE, TestIfaceClass)) - +#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass)) +typedef struct _TestIface TestIface; +typedef struct _TestIfaceClass TestIfaceClass; +struct _TestIfaceClass +{ + GTypeInterface base_iface; + void (*print_string) (TestIface *tiobj, + const gchar *string); +}; +static void iface_base_init (TestIfaceClass *iface); +static void iface_base_finalize (TestIfaceClass *iface); +static void print_foo (TestIface *tiobj, + const gchar *string); GType test_iface_get_type (void) { @@ -52,8 +48,8 @@ test_iface_get_type (void) static const GTypeInfo test_iface_info = { sizeof (TestIfaceClass), - NULL, /* base_init */ - NULL, /* base_finalize */ + (GBaseInitFunc) iface_base_init, /* base_init */ + (GBaseFinalizeFunc) iface_base_finalize, /* base_finalize */ }; test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0); @@ -62,21 +58,141 @@ test_iface_get_type (void) return test_iface_type; } +static guint iface_base_init_count = 0; +static void +iface_base_init (TestIfaceClass *iface) +{ + iface_base_init_count++; + if (iface_base_init_count == 1) + { + /* add signals here */ + } +} +static void +iface_base_finalize (TestIfaceClass *iface) +{ + iface_base_init_count--; + if (iface_base_init_count == 0) + { + /* destroy signals here */ + } +} +static void +print_foo (TestIface *tiobj, + const gchar *string) +{ + if (!string) + string = ""; + g_print ("Iface-FOO: \"%s\" from %p\n", string, tiobj); +} +static void +test_object_test_iface_init (gpointer giface, + gpointer iface_data) +{ + TestIfaceClass *iface = giface; -typedef struct + g_assert (iface_data == GUINT_TO_POINTER (42)); + + g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE); + + /* assert iface_base_init() was already called */ + g_assert (iface_base_init_count > 0); + + /* initialize stuff */ + iface->print_string = print_foo; +} +void +iface_print_string (TestIface *tiobj, + const gchar *string) +{ + TestIfaceClass *iface; + + g_return_if_fail (TEST_IS_IFACE (tiobj)); + g_return_if_fail (G_IS_OBJECT (tiobj)); /* ensured through prerequisite */ + + iface = TEST_IFACE_GET_CLASS (tiobj); + g_object_ref (tiobj); + iface->print_string (tiobj, string); + g_object_unref (tiobj); +} + + +/* --- TestObject --- */ +#define TEST_TYPE_OBJECT (test_object_get_type ()) +#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) +#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) +#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) +#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) +#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) +typedef struct _TestObject TestObject; +typedef struct _TestObjectClass TestObjectClass; +struct _TestObject +{ + GObject parent_instance; +}; +struct _TestObjectClass { GObjectClass parent_class; gchar* (*test_signal) (TestObject *tobject, TestIface *iface_object, gpointer tdata); -} TestObjectClass; +}; +static void test_object_class_init (TestObjectClass *class); +static void test_object_init (TestObject *tobject); +static gboolean test_signal_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data); +static gchar* test_object_test_signal (TestObject *tobject, + TestIface *iface_object, + gpointer tdata); +GType +test_object_get_type (void) +{ + static GType test_object_type = 0; + if (!test_object_type) + { + static const GTypeInfo test_object_info = + { + sizeof (TestObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) test_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (TestObject), + 5, /* n_preallocs */ + (GInstanceInitFunc) test_object_init, + }; + GInterfaceInfo iface_info = { test_object_test_iface_init, NULL, GUINT_TO_POINTER (42) }; + + test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); + g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + } + + return test_object_type; +} +static void +test_object_class_init (TestObjectClass *class) +{ + /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + + class->test_signal = test_object_test_signal; + + g_signal_new ("test-signal", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, + G_STRUCT_OFFSET (TestObjectClass, test_signal), + test_signal_accumulator, NULL, + g_cclosure_marshal_STRING__OBJECT_POINTER, + G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); +} static void test_object_init (TestObject *tobject) { } - static gboolean test_signal_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, @@ -98,7 +214,6 @@ test_signal_accumulator (GSignalInvocationHint *ihint, return TRUE; } - static gchar* test_object_test_signal (TestObject *tobject, TestIface *iface_object, @@ -111,57 +226,90 @@ test_object_test_signal (TestObject *tobject, return g_strdup (""); } + +/* --- TestIface for DerivedObject --- */ static void -test_object_class_init (TestObjectClass *class) +print_bar (TestIface *tiobj, + const gchar *string) { - /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + TestIfaceClass *parent_iface; - class->test_signal = test_object_test_signal; + g_return_if_fail (TEST_IS_IFACE (tiobj)); - g_signal_new ("test-signal", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, - G_STRUCT_OFFSET (TestObjectClass, test_signal), - test_signal_accumulator, NULL, - g_cclosure_marshal_STRING__OBJECT_POINTER, - G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); + if (!string) + string = ""; + g_print ("Iface-BAR: \"%s\" from %p\n", string, tiobj); + + g_print ("chaining: "); + parent_iface = g_type_interface_peek_parent (TEST_IFACE_GET_CLASS (tiobj)); + parent_iface->print_string (tiobj, string); + + g_assert (g_type_interface_peek_parent (parent_iface) == NULL); } -GType -test_object_get_type (void) +static void +derived_object_test_iface_init (gpointer giface, + gpointer iface_data) { - static GType test_object_type = 0; + TestIfaceClass *iface = giface; - if (!test_object_type) + g_assert (iface_data == GUINT_TO_POINTER (87)); + + g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE); + + /* assert test_object_test_iface_init() was already called */ + g_assert (iface->print_string == print_foo); + + /* override stuff */ + iface->print_string = print_bar; +} + + +/* --- DerivedObject --- */ +#define DERIVED_TYPE_OBJECT (derived_object_get_type ()) +#define DERIVED_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DERIVED_TYPE_OBJECT, DerivedObject)) +#define DERIVED_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DERIVED_TYPE_OBJECT, DerivedObjectClass)) +#define DERIVED_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DERIVED_TYPE_OBJECT)) +#define DERIVED_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DERIVED_TYPE_OBJECT)) +#define DERIVED_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DERIVED_TYPE_OBJECT, DerivedObjectClass)) +typedef struct _TestObject DerivedObject; +typedef struct _TestObjectClass DerivedObjectClass; +GType +derived_object_get_type (void) +{ + static GType derived_object_type = 0; + + if (!derived_object_type) { - static const GTypeInfo test_object_info = + static const GTypeInfo derived_object_info = { - sizeof (TestObjectClass), + sizeof (DerivedObjectClass), NULL, /* base_init */ NULL, /* base_finalize */ - (GClassInitFunc) test_object_class_init, + NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ - sizeof (TestObject), + sizeof (DerivedObject), 5, /* n_preallocs */ - (GInstanceInitFunc) test_object_init, + NULL, /* instance_init */ }; - GInterfaceInfo iface_info = { NULL, NULL, NULL }; + GInterfaceInfo iface_info = { derived_object_test_iface_init, NULL, GUINT_TO_POINTER (87) }; - test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); - g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + derived_object_type = g_type_register_static (TEST_TYPE_OBJECT, "DerivedObject", &derived_object_info, 0); + g_type_add_interface_static (derived_object_type, TEST_TYPE_IFACE, &iface_info); } - return test_object_type; + return derived_object_type; } - +/* --- main --- */ int main (int argc, char *argv[]) { - TestObject *tobject, *sigarg; + TestObject *sigarg; + DerivedObject *dobject; gchar *string = NULL; g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) | @@ -169,14 +317,24 @@ main (int argc, G_LOG_LEVEL_CRITICAL); g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); - tobject = g_object_new (TEST_TYPE_OBJECT, NULL); + /* to test past class initialization interface setups, create the class here */ + g_type_class_ref (TEST_TYPE_OBJECT); + + dobject = g_object_new (DERIVED_TYPE_OBJECT, NULL); sigarg = g_object_new (TEST_TYPE_OBJECT, NULL); - g_signal_emit_by_name (tobject, "test-signal", sigarg, NULL, &string); + + g_print ("MAIN: emit test-signal:\n"); + g_signal_emit_by_name (dobject, "test-signal", sigarg, NULL, &string); g_message ("signal return: \"%s\"", string); + g_assert (strcmp (string, "") == 0); g_free (string); + + g_print ("MAIN: call iface print-string on test and derived object:\n"); + iface_print_string (TEST_IFACE (sigarg), "iface-string-from-test-type"); + iface_print_string (TEST_IFACE (dobject), "iface-string-from-derived-type"); g_object_unref (sigarg); - g_object_unref (tobject); + g_object_unref (dobject); g_message ("%s done", argv[0]); diff --git a/gobject/testgruntime.c b/gobject/testgruntime.c index ef8a755d5..e7d5216ce 100644 --- a/gobject/testgruntime.c +++ b/gobject/testgruntime.c @@ -20,28 +20,24 @@ #define G_LOG_DOMAIN "TestObject" #include -#define TEST_TYPE_OBJECT (test_object_get_type ()) -#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) -#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) -#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) -#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) -#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) - -typedef struct _TestIface TestIface; -typedef struct -{ - GTypeInterface base_iface; -} TestIfaceClass; -typedef struct -{ - GObject parent_instance; -} TestObject; +/* --- TestIface --- */ #define TEST_TYPE_IFACE (test_iface_get_type ()) #define TEST_IFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_TYPE_IFACE, TestIface)) #define TEST_IS_IFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEST_TYPE_IFACE)) -#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), TEST_TYPE_IFACE, TestIfaceClass)) - +#define TEST_IFACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), TEST_TYPE_IFACE, TestIfaceClass)) +typedef struct _TestIface TestIface; +typedef struct _TestIfaceClass TestIfaceClass; +struct _TestIfaceClass +{ + GTypeInterface base_iface; + void (*print_string) (TestIface *tiobj, + const gchar *string); +}; +static void iface_base_init (TestIfaceClass *iface); +static void iface_base_finalize (TestIfaceClass *iface); +static void print_foo (TestIface *tiobj, + const gchar *string); GType test_iface_get_type (void) { @@ -52,8 +48,8 @@ test_iface_get_type (void) static const GTypeInfo test_iface_info = { sizeof (TestIfaceClass), - NULL, /* base_init */ - NULL, /* base_finalize */ + (GBaseInitFunc) iface_base_init, /* base_init */ + (GBaseFinalizeFunc) iface_base_finalize, /* base_finalize */ }; test_iface_type = g_type_register_static (G_TYPE_INTERFACE, "TestIface", &test_iface_info, 0); @@ -62,21 +58,141 @@ test_iface_get_type (void) return test_iface_type; } +static guint iface_base_init_count = 0; +static void +iface_base_init (TestIfaceClass *iface) +{ + iface_base_init_count++; + if (iface_base_init_count == 1) + { + /* add signals here */ + } +} +static void +iface_base_finalize (TestIfaceClass *iface) +{ + iface_base_init_count--; + if (iface_base_init_count == 0) + { + /* destroy signals here */ + } +} +static void +print_foo (TestIface *tiobj, + const gchar *string) +{ + if (!string) + string = ""; + g_print ("Iface-FOO: \"%s\" from %p\n", string, tiobj); +} +static void +test_object_test_iface_init (gpointer giface, + gpointer iface_data) +{ + TestIfaceClass *iface = giface; -typedef struct + g_assert (iface_data == GUINT_TO_POINTER (42)); + + g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE); + + /* assert iface_base_init() was already called */ + g_assert (iface_base_init_count > 0); + + /* initialize stuff */ + iface->print_string = print_foo; +} +void +iface_print_string (TestIface *tiobj, + const gchar *string) +{ + TestIfaceClass *iface; + + g_return_if_fail (TEST_IS_IFACE (tiobj)); + g_return_if_fail (G_IS_OBJECT (tiobj)); /* ensured through prerequisite */ + + iface = TEST_IFACE_GET_CLASS (tiobj); + g_object_ref (tiobj); + iface->print_string (tiobj, string); + g_object_unref (tiobj); +} + + +/* --- TestObject --- */ +#define TEST_TYPE_OBJECT (test_object_get_type ()) +#define TEST_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TEST_TYPE_OBJECT, TestObject)) +#define TEST_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TEST_TYPE_OBJECT, TestObjectClass)) +#define TEST_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TEST_TYPE_OBJECT)) +#define TEST_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TEST_TYPE_OBJECT)) +#define TEST_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TEST_TYPE_OBJECT, TestObjectClass)) +typedef struct _TestObject TestObject; +typedef struct _TestObjectClass TestObjectClass; +struct _TestObject +{ + GObject parent_instance; +}; +struct _TestObjectClass { GObjectClass parent_class; gchar* (*test_signal) (TestObject *tobject, TestIface *iface_object, gpointer tdata); -} TestObjectClass; +}; +static void test_object_class_init (TestObjectClass *class); +static void test_object_init (TestObject *tobject); +static gboolean test_signal_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer data); +static gchar* test_object_test_signal (TestObject *tobject, + TestIface *iface_object, + gpointer tdata); +GType +test_object_get_type (void) +{ + static GType test_object_type = 0; + if (!test_object_type) + { + static const GTypeInfo test_object_info = + { + sizeof (TestObjectClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) test_object_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (TestObject), + 5, /* n_preallocs */ + (GInstanceInitFunc) test_object_init, + }; + GInterfaceInfo iface_info = { test_object_test_iface_init, NULL, GUINT_TO_POINTER (42) }; + + test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); + g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + } + + return test_object_type; +} +static void +test_object_class_init (TestObjectClass *class) +{ + /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + + class->test_signal = test_object_test_signal; + + g_signal_new ("test-signal", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, + G_STRUCT_OFFSET (TestObjectClass, test_signal), + test_signal_accumulator, NULL, + g_cclosure_marshal_STRING__OBJECT_POINTER, + G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); +} static void test_object_init (TestObject *tobject) { } - static gboolean test_signal_accumulator (GSignalInvocationHint *ihint, GValue *return_accu, @@ -98,7 +214,6 @@ test_signal_accumulator (GSignalInvocationHint *ihint, return TRUE; } - static gchar* test_object_test_signal (TestObject *tobject, TestIface *iface_object, @@ -111,57 +226,90 @@ test_object_test_signal (TestObject *tobject, return g_strdup (""); } + +/* --- TestIface for DerivedObject --- */ static void -test_object_class_init (TestObjectClass *class) +print_bar (TestIface *tiobj, + const gchar *string) { - /* GObjectClass *gobject_class = G_OBJECT_CLASS (class); */ + TestIfaceClass *parent_iface; - class->test_signal = test_object_test_signal; + g_return_if_fail (TEST_IS_IFACE (tiobj)); - g_signal_new ("test-signal", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP, - G_STRUCT_OFFSET (TestObjectClass, test_signal), - test_signal_accumulator, NULL, - g_cclosure_marshal_STRING__OBJECT_POINTER, - G_TYPE_STRING, 2, TEST_TYPE_IFACE, G_TYPE_POINTER); + if (!string) + string = ""; + g_print ("Iface-BAR: \"%s\" from %p\n", string, tiobj); + + g_print ("chaining: "); + parent_iface = g_type_interface_peek_parent (TEST_IFACE_GET_CLASS (tiobj)); + parent_iface->print_string (tiobj, string); + + g_assert (g_type_interface_peek_parent (parent_iface) == NULL); } -GType -test_object_get_type (void) +static void +derived_object_test_iface_init (gpointer giface, + gpointer iface_data) { - static GType test_object_type = 0; + TestIfaceClass *iface = giface; - if (!test_object_type) + g_assert (iface_data == GUINT_TO_POINTER (87)); + + g_assert (G_TYPE_FROM_INTERFACE (iface) == TEST_TYPE_IFACE); + + /* assert test_object_test_iface_init() was already called */ + g_assert (iface->print_string == print_foo); + + /* override stuff */ + iface->print_string = print_bar; +} + + +/* --- DerivedObject --- */ +#define DERIVED_TYPE_OBJECT (derived_object_get_type ()) +#define DERIVED_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), DERIVED_TYPE_OBJECT, DerivedObject)) +#define DERIVED_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DERIVED_TYPE_OBJECT, DerivedObjectClass)) +#define DERIVED_IS_OBJECT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), DERIVED_TYPE_OBJECT)) +#define DERIVED_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DERIVED_TYPE_OBJECT)) +#define DERIVED_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DERIVED_TYPE_OBJECT, DerivedObjectClass)) +typedef struct _TestObject DerivedObject; +typedef struct _TestObjectClass DerivedObjectClass; +GType +derived_object_get_type (void) +{ + static GType derived_object_type = 0; + + if (!derived_object_type) { - static const GTypeInfo test_object_info = + static const GTypeInfo derived_object_info = { - sizeof (TestObjectClass), + sizeof (DerivedObjectClass), NULL, /* base_init */ NULL, /* base_finalize */ - (GClassInitFunc) test_object_class_init, + NULL, /* class_init */ NULL, /* class_finalize */ NULL, /* class_data */ - sizeof (TestObject), + sizeof (DerivedObject), 5, /* n_preallocs */ - (GInstanceInitFunc) test_object_init, + NULL, /* instance_init */ }; - GInterfaceInfo iface_info = { NULL, NULL, NULL }; + GInterfaceInfo iface_info = { derived_object_test_iface_init, NULL, GUINT_TO_POINTER (87) }; - test_object_type = g_type_register_static (G_TYPE_OBJECT, "TestObject", &test_object_info, 0); - g_type_add_interface_static (test_object_type, TEST_TYPE_IFACE, &iface_info); + derived_object_type = g_type_register_static (TEST_TYPE_OBJECT, "DerivedObject", &derived_object_info, 0); + g_type_add_interface_static (derived_object_type, TEST_TYPE_IFACE, &iface_info); } - return test_object_type; + return derived_object_type; } - +/* --- main --- */ int main (int argc, char *argv[]) { - TestObject *tobject, *sigarg; + TestObject *sigarg; + DerivedObject *dobject; gchar *string = NULL; g_log_set_always_fatal (g_log_set_always_fatal (G_LOG_FATAL_MASK) | @@ -169,14 +317,24 @@ main (int argc, G_LOG_LEVEL_CRITICAL); g_type_init_with_debug_flags (G_TYPE_DEBUG_OBJECTS | G_TYPE_DEBUG_SIGNALS); - tobject = g_object_new (TEST_TYPE_OBJECT, NULL); + /* to test past class initialization interface setups, create the class here */ + g_type_class_ref (TEST_TYPE_OBJECT); + + dobject = g_object_new (DERIVED_TYPE_OBJECT, NULL); sigarg = g_object_new (TEST_TYPE_OBJECT, NULL); - g_signal_emit_by_name (tobject, "test-signal", sigarg, NULL, &string); + + g_print ("MAIN: emit test-signal:\n"); + g_signal_emit_by_name (dobject, "test-signal", sigarg, NULL, &string); g_message ("signal return: \"%s\"", string); + g_assert (strcmp (string, "") == 0); g_free (string); + + g_print ("MAIN: call iface print-string on test and derived object:\n"); + iface_print_string (TEST_IFACE (sigarg), "iface-string-from-test-type"); + iface_print_string (TEST_IFACE (dobject), "iface-string-from-derived-type"); g_object_unref (sigarg); - g_object_unref (tobject); + g_object_unref (dobject); g_message ("%s done", argv[0]);