got rid of g_set_error_handler(), g_set_warning_handler(),

Mon Sep 10 17:13:36 2001  Tim Janik  <timj@gtk.org>

        * glib/gmessages.h: got rid of g_set_error_handler(),
        g_set_warning_handler(), g_set_message_handler().

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 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.
This commit is contained in:
Tim Janik 2001-09-10 18:03:31 +00:00 committed by Tim Janik
parent ae2c2ca6c3
commit dc0b74d416
27 changed files with 770 additions and 390 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -777,14 +777,6 @@ g_log_set_always_fatal
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>

View File

@ -1,3 +1,29 @@
<!-- ##### 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>
@ -51,6 +77,13 @@
@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>
@ -71,6 +104,13 @@
@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>
@ -223,6 +263,33 @@ documentation.
@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>

View File

@ -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.
<!-- ##### 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.

View File

@ -234,6 +234,7 @@ g_flags_complete_type_info
<FILE>gboxed</FILE>
<TITLE>Boxed Types</TITLE>
GBoxed
GBoxedInitFunc
GBoxedCopyFunc
GBoxedFreeFunc
g_boxed_copy

View File

@ -1,12 +1,11 @@
<!-- ##### SECTION Title ##### -->
Enumeration and Flag Types
Enums and Flags
<!-- ##### SECTION Short_Description ##### -->
Enumeration and flags types.
<!-- ##### SECTION Long_Description ##### -->
<para>
</para>
<!-- ##### SECTION See_Also ##### -->

View File

@ -1,8 +1,8 @@
<!-- ##### SECTION Title ##### -->
gboxed
GBoxed
<!-- ##### SECTION Short_Description ##### -->
Mechanism to wrap opaque C structures registered by the type system.
<!-- ##### SECTION Long_Description ##### -->
<para>
@ -11,52 +11,55 @@ gboxed
<!-- ##### 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 ##### -->
@ -97,14 +100,17 @@ This is an internal function introduced mainly for C marshallers.
<!-- ##### 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:

View File

@ -4,6 +4,13 @@
</para>
<!-- ##### USER_FUNCTION GBoxedInitFunc ##### -->
<para>
</para>
@Returns:
<!-- ##### FUNCTION g_closure_add_fnotify ##### -->
<para>

View File

@ -1,8 +1,8 @@
<!-- ##### SECTION Title ##### -->
The Base Object Type
GObject
<!-- ##### SECTION Short_Description ##### -->
The base object type.
<!-- ##### SECTION Long_Description ##### -->
<para>
@ -16,7 +16,8 @@ The Base Object Type
<!-- ##### 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:
@ -71,26 +72,30 @@ The Base Object Type
<!-- ##### 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 ##### -->
@ -119,10 +124,11 @@ The Base Object Type
<!-- ##### 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 ##### -->
@ -256,8 +262,8 @@ lifetime of @object. When the @object is finalized, @weak_pointer will
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 ##### -->
@ -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().
</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 ##### -->
@ -302,8 +308,6 @@ to match the one used with g_object_add_weak_pointer().
@first_property_name:
@Varargs:
@Returns:
<!-- # Unused Parameters # -->
@first_param_name:
<!-- ##### FUNCTION g_object_get ##### -->
@ -314,8 +318,6 @@ to match the one used with g_object_add_weak_pointer().
@object:
@first_property_name:
@Varargs:
<!-- # Unused Parameters # -->
@first_param_name:
<!-- ##### FUNCTION g_object_notify ##### -->
@ -454,8 +456,6 @@ to match the one used with g_object_add_weak_pointer().
@first_property_name:
@var_args:
@Returns:
<!-- # Unused Parameters # -->
@first_param_name:
<!-- ##### FUNCTION g_object_set_valist ##### -->
@ -466,8 +466,6 @@ to match the one used with g_object_add_weak_pointer().
@object:
@first_property_name:
@var_args:
<!-- # Unused Parameters # -->
@first_param_name:
<!-- ##### FUNCTION g_object_get_valist ##### -->
@ -478,8 +476,6 @@ to match the one used with g_object_add_weak_pointer().
@object:
@first_property_name:
@var_args:
<!-- # Unused Parameters # -->
@first_param_name:
<!-- ##### FUNCTION g_object_watch_closure ##### -->

View File

@ -13,7 +13,7 @@ in order for it to be used as a boxed type through %G_TYPE_VALUE_ARRAY.
<!-- ##### SECTION See_Also ##### -->
<para>
#GValue, #GParamSpecValueArray
#GValue, #GParamSpecValueArray, g_param_spec_value_array()
</para>
<!-- ##### STRUCT GValueArray ##### -->

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
return iholder;
}
if (!iholder->info)
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;
g_assert (entry && entry->vtable == vtable);
/* 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);
@ -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,6 +2091,37 @@ 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;

View File

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

View File

@ -20,28 +20,24 @@
#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)
{
@ -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 = "<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;
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 ("<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);
}
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, "<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]);

View File

@ -20,28 +20,24 @@
#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)
{
@ -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 = "<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;
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 ("<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);
}
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, "<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]);