-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
-2001-09-10 Alex Larsson <alexl@redhat.com>
+Mon Sep 10 17:13:36 2001 Tim Janik <timj@gtk.org>
- * 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 <otaylor@redhat.com>
@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.
+
+Wed Sep 5 05:24:07 2001 Tim Janik <timj@gtk.org>
+
+ * gobject/tmpl/gboxed.sgml: documented some functions.
+
+ * gobject/tmpl/objects.sgml: some fixups.
+
Mon Sep 10 11:37:02 2001 Owen Taylor <otaylor@redhat.com>
* glib/glib-sections.txt: Update.
g_log_set_fatal_mask
g_log_default_handler
-<SUBSECTION>
-g_set_error_handler
-GErrorFunc
-g_set_warning_handler
-GWarningFunc
-g_set_message_handler
-</SECTION>
-
<SECTION>
<TITLE>Timers</TITLE>
<FILE>timers</FILE>
+<!-- ##### SECTION ./tmpl/messages.sgml:Long_Description ##### -->
+<para>
+These functions provide support for logging error messages or messages
+used for debugging.
+</para>
+
+<para>
+There are several built-in levels of messages, defined in #GLogLevelFlags.
+These can be extended with user-defined levels.
+</para>
+
+
+<!-- ##### SECTION ./tmpl/messages.sgml:See_Also ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### SECTION ./tmpl/messages.sgml:Short_Description ##### -->
+versatile support for logging messages with different levels of importance.
+
+
+<!-- ##### SECTION ./tmpl/messages.sgml:Title ##### -->
+Message Logging
+
+
<!-- ##### ENUM GChannelError ##### -->
<para>
@s2:
@Returns:
+<!-- ##### USER_FUNCTION GErrorFunc ##### -->
+<para>
+Specifies the type of function passed to g_set_error_handler().
+</para>
+
+@str: the error message.
+
<!-- ##### USER_FUNCTION GHookFreeFunc ##### -->
<para>
@G_IO_FILE_MODE_READ_WRITE_TRUNCATE:
@G_IO_FILE_MODE_READ_WRITE_APPEND:
+<!-- ##### USER_FUNCTION GWarningFunc ##### -->
+<para>
+Specifies the type of function passed to g_set_warning_handler().
+</para>
+
+@str: the warning message.
+
<!-- ##### MACRO G_CHANNEL_ERROR ##### -->
<para>
@filename: the file name.
@Returns: the file attributes.
+<!-- ##### FUNCTION g_set_error_handler ##### -->
+<para>
+Sets the function to be called to handle error messages.
+This function is deprecated in favour of the new logging facilities.
+</para>
+
+@func: the function to be called to handle error messages.
+@Returns: the old error handler.
+
+<!-- ##### FUNCTION g_set_message_handler ##### -->
+<para>
+Sets the function to be called to handle messages.
+This function is deprecated in favour of the new logging facilities.
+</para>
+
+@func: the function to be called to handle normal messages.
+@Returns: the old message handler.
+
+<!-- ##### FUNCTION g_set_warning_handler ##### -->
+<para>
+Sets the function to be called to handle warning messages.
+This function is deprecated in favour of the new logging facilities.
+</para>
+
+@func: the function to be called to handle warning messages.
+@Returns: the old warning handler.
+
<!-- ##### FUNCTION g_source_add ##### -->
<para>
</para>
@unused_data: data passed from g_log which is unused.
-<!-- ##### FUNCTION g_set_error_handler ##### -->
-<para>
-Sets the function to be called to handle error messages.
-This function is deprecated in favour of the new logging facilities.
-</para>
-
-@func: the function to be called to handle error messages.
-@Returns: the old error handler.
-
-
-<!-- ##### USER_FUNCTION GErrorFunc ##### -->
-<para>
-Specifies the type of function passed to g_set_error_handler().
-</para>
-
-@str: the error message.
-
-
-<!-- ##### FUNCTION g_set_warning_handler ##### -->
-<para>
-Sets the function to be called to handle warning messages.
-This function is deprecated in favour of the new logging facilities.
-</para>
-
-@func: the function to be called to handle warning messages.
-@Returns: the old warning handler.
-
-
-<!-- ##### USER_FUNCTION GWarningFunc ##### -->
-<para>
-Specifies the type of function passed to g_set_warning_handler().
-</para>
-
-@str: the warning message.
-
-
-<!-- ##### FUNCTION g_set_message_handler ##### -->
-<para>
-Sets the function to be called to handle messages.
-This function is deprecated in favour of the new logging facilities.
-</para>
-
-@func: the function to be called to handle normal messages.
-@Returns: the old message handler.
-
-
<FILE>gboxed</FILE>
<TITLE>Boxed Types</TITLE>
GBoxed
+GBoxedInitFunc
GBoxedCopyFunc
GBoxedFreeFunc
g_boxed_copy
<!-- ##### SECTION Title ##### -->
-Enumeration and Flag Types
+Enums and Flags
<!-- ##### SECTION Short_Description ##### -->
-
+Enumeration and flags types.
<!-- ##### SECTION Long_Description ##### -->
<para>
-
</para>
<!-- ##### SECTION See_Also ##### -->
<!-- ##### SECTION Title ##### -->
-gboxed
+GBoxed
<!-- ##### SECTION Short_Description ##### -->
-
+Mechanism to wrap opaque C structures registered by the type system.
<!-- ##### SECTION Long_Description ##### -->
<para>
<!-- ##### SECTION See_Also ##### -->
<para>
-
+#GParamSpecBoxed, g_param_spec_boxed()
</para>
<!-- ##### USER_FUNCTION GBoxedCopyFunc ##### -->
<para>
-
+This function is provided by the user and should produce a copy of the passed
+in boxed structure.
</para>
-@boxed:
-@Returns:
+@boxed: The boxed structure to be copied.
+@Returns: The newly created copy of the boxed structure.
<!-- ##### USER_FUNCTION GBoxedFreeFunc ##### -->
<para>
-
+This function is provided by the user and should free the boxed
+structure passed.
</para>
-@boxed:
+@boxed: The boxed structure to be freed.
<!-- ##### FUNCTION g_boxed_copy ##### -->
<para>
-
+Provide a copy of a boxed structure @src_boxed which is of type @boxed_type.
</para>
-@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.
<!-- ##### FUNCTION g_boxed_free ##### -->
<para>
-
+Free the boxed structure @boxed which is of type @boxed_type.
</para>
-@boxed_type:
-@boxed:
+@boxed_type: The type of @boxed.
+@boxed: The boxed structure to be freed.
<!-- ##### FUNCTION g_value_set_boxed ##### -->
<para>
-
+Assign a #GValue which is initialized with a certain boxed type a
+boxed structure of that very same type.
</para>
-@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.
<!-- ##### FUNCTION g_value_set_static_boxed ##### -->
<!-- ##### FUNCTION g_boxed_type_register_static ##### -->
<para>
-
+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.
</para>
-@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.
+<!-- # Unused Parameters # -->
@boxed_init:
-@boxed_copy:
-@boxed_free:
@is_refcounted:
-@Returns:
</para>
+<!-- ##### USER_FUNCTION GBoxedInitFunc ##### -->
+<para>
+
+</para>
+
+@Returns:
+
<!-- ##### FUNCTION g_closure_add_fnotify ##### -->
<para>
<!-- ##### SECTION Title ##### -->
-The Base Object Type
+GObject
<!-- ##### SECTION Short_Description ##### -->
-
+The base object type.
<!-- ##### SECTION Long_Description ##### -->
<para>
<!-- ##### STRUCT GObject ##### -->
<para>
-
+All the fields in the GObject structure are private to the #GObject implementation
+and should never be accessed directly.
</para>
@g_type_instance:
<!-- ##### MACRO G_TYPE_IS_OBJECT ##### -->
<para>
-
+Return a boolean value of %FALSE or %TRUE indicating whether
+the passed in type id is a %G_TYPE_OBJECT or derived from it.
</para>
-@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.
<!-- ##### MACRO G_OBJECT ##### -->
<para>
-
+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.
</para>
-@object:
+@object: Object which is subject to casting.
<!-- ##### MACRO G_IS_OBJECT ##### -->
<para>
-
+Check whether a valid #GTypeInstance pointer is of type %G_TYPE_OBJECT.
</para>
-@object:
+@object: Instance to check for being a %G_TYPE_OBJECT.
<!-- ##### MACRO G_OBJECT_CLASS ##### -->
<!-- ##### MACRO G_OBJECT_TYPE ##### -->
<para>
-
+Return the type id of an object.
</para>
-@object:
+@object: Object to return the type id for.
+@Returns: Type id of @object.
<!-- ##### MACRO G_OBJECT_TYPE_NAME ##### -->
be set to %NULL.
</para>
-@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.
<!-- ##### FUNCTION g_object_remove_weak_pointer ##### -->
to match the one used with g_object_add_weak_pointer().
</para>
-@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.
<!-- ##### FUNCTION g_object_connect ##### -->
@first_property_name:
@Varargs:
@Returns:
-<!-- # Unused Parameters # -->
-@first_param_name:
<!-- ##### FUNCTION g_object_get ##### -->
@object:
@first_property_name:
@Varargs:
-<!-- # Unused Parameters # -->
-@first_param_name:
<!-- ##### FUNCTION g_object_notify ##### -->
@first_property_name:
@var_args:
@Returns:
-<!-- # Unused Parameters # -->
-@first_param_name:
<!-- ##### FUNCTION g_object_set_valist ##### -->
@object:
@first_property_name:
@var_args:
-<!-- # Unused Parameters # -->
-@first_param_name:
<!-- ##### FUNCTION g_object_get_valist ##### -->
@object:
@first_property_name:
@var_args:
-<!-- # Unused Parameters # -->
-@first_param_name:
<!-- ##### FUNCTION g_object_watch_closure ##### -->
<!-- ##### SECTION See_Also ##### -->
<para>
-#GValue, #GParamSpecValueArray
+#GValue, #GParamSpecValueArray, g_param_spec_value_array()
</para>
<!-- ##### STRUCT GValueArray ##### -->
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
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;
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;
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);
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);
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);
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
...) 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
+Mon Sep 10 19:27:47 2001 Tim Janik <timj@gtk.org>
+
+ * 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 <alexl@redhat.com>
+
+ * 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 <otaylor@redhat.com>
* gobject/Makefile.am: Move gbsearcharray.[ch] to glib
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 --- */
}
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++;
}
static TypeNode*
-find_conforming_type_L (TypeNode *pnode,
- TypeNode *iface)
+find_conforming_child_type_L (TypeNode *pnode,
+ TypeNode *iface)
{
TypeNode *node = NULL;
guint i;
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;
}
{
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)
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",
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)
}
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;
iholder->info = g_memdup (&tmp_info, sizeof (tmp_info));
}
- return iholder;
+ return iholder; /* we don't modify write lock upon returning NULL */
}
static void
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);
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);
-
- g_assert (entry && entry->vtable == vtable);
+ 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 */
- while (iholder->instance_type != NODE_TYPE (node))
- iholder = iholder->next;
- g_assert (iholder && iholder->info);
+ g_assert (entry && entry->vtable == vtable && 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);
g_free (vtable);
type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
+
+ return TRUE; /* write lock modified */
}
static void
GSList *slist, *init_slist = NULL;
GTypeClass *class;
IFaceEntry *entry;
- TypeNode *bnode;
+ TypeNode *bnode, *pnode;
guint i;
g_assert (node->is_classed && node->data &&
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;
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))
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);
}
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);
}
g_type_class_peek_parent (gpointer g_class)
{
TypeNode *node;
- gpointer class;
+ gpointer class = NULL;
g_return_val_if_fail (g_class != NULL, NULL);
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;
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)
{
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,
#define G_LOG_DOMAIN "TestObject"
#include <glib-object.h>
-#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)
{
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);
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 = "<NULL>";
+ 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;
+
+ 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);
+}
-typedef struct
+
+/* --- 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,
return TRUE;
}
-
static gchar*
test_object_test_signal (TestObject *tobject,
TestIface *iface_object,
return g_strdup ("<default_handler>");
}
+
+/* --- 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 = "<NULL>";
+ 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);
+}
+
+static void
+derived_object_test_iface_init (gpointer giface,
+ gpointer iface_data)
+{
+ TestIfaceClass *iface = giface;
+
+ 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
-test_object_get_type (void)
+derived_object_get_type (void)
{
- static GType test_object_type = 0;
+ static GType derived_object_type = 0;
- if (!test_object_type)
+ 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) |
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, "<default_handler><default_handler>") == 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]);
#define G_LOG_DOMAIN "TestObject"
#include <glib-object.h>
-#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)
{
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);
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 = "<NULL>";
+ 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;
+
+ 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);
+}
-typedef struct
+
+/* --- 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,
return TRUE;
}
-
static gchar*
test_object_test_signal (TestObject *tobject,
TestIface *iface_object,
return g_strdup ("<default_handler>");
}
+
+/* --- 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 = "<NULL>";
+ 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);
+}
+
+static void
+derived_object_test_iface_init (gpointer giface,
+ gpointer iface_data)
+{
+ TestIfaceClass *iface = giface;
+
+ 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
-test_object_get_type (void)
+derived_object_get_type (void)
{
- static GType test_object_type = 0;
+ static GType derived_object_type = 0;
- if (!test_object_type)
+ 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) |
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, "<default_handler><default_handler>") == 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]);