From: Nick Bowler Date: Thu, 6 Feb 2020 05:07:44 +0000 (-0500) Subject: Fix dynamic interface implementation. X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/commitdiff_plain/43115cbfefb29535b3e9da83ab247a7f24c6994b Fix dynamic interface implementation. When a dynamic type implements an interface and derives from a type which implements the same interface, the g_type_module_add_interface function does not actually work: no interface will be added to the dynamic type in this case. The bug is in the GTypeModule class implementation in gobject, the actual type system has no such limitation. It is reasonably straightforward to hack around the problem in GOB. --- diff --git a/src/main.c b/src/main.c index 424f12c..6a0c791 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,7 @@ * Copyright (C) 1999,2000 the Free Software Foundation. * Copyright (C) 2000 Eazel, Inc. * Copyright (C) 2001-2011 George (Jiri) Lebl + * Copyright © 2019-2020 Nick Bowler * * Author: George (Jiri) Lebl * @@ -1129,20 +1130,46 @@ add_interfaces (void) static void add_dynamic_interfaces(void) { - GList *li; - for (li = ((Class *)class)->interfaces; - li != NULL; - li = li ->next) { - char *name = replace_sep (li->data, '_'); - char *type = make_pre_macro (li->data, "TYPE"); + GList *li = ((Class *)class)->interfaces; - out_printf(out, - "\t\tg_type_module_add_interface(\n" - "\t\t\ttype_module,\n" - "\t\t\t%s_type_id,\n" - "\t\t\t%s,\n" - "\t\t\t&%s_info);\n", - funcbase, type, name); + if (li) { + /* + * Hack to work around bug in g_type_module_add_interface, + * which will fail to add an interface to types that derive + * from something that also implements the same interface. + * + * The actual GType system does not have any such problem, + * and the GTypeModule implementation details relied upon + * here have not changed once since the feature was first + * implemented almost 20 years ago. + */ + out_printf(out, "\t\tstruct _ModuleInterfaceInfo {\n" + "\t\t\tgboolean loaded;\n" + "\t\t\tGType instance_type;\n" + "\t\t\tGType interface_type;\n" + "\t\t\tGInterfaceInfo info;\n" + "\t\t} *modinfo;\n"); + } + + for (; li; li = li->next) { + char *name = replace_sep(li->data, '_'); + char *type = make_pre_macro(li->data, "TYPE"); + + out_printf(out, "\n" + "\t\tmodinfo = g_malloc(sizeof *modinfo);\n" + "\t\tmodinfo->loaded = TRUE;\n" + "\t\tmodinfo->instance_type = %s_type_id;\n" + "\t\tmodinfo->interface_type = %s;\n" + "\t\tmodinfo->info = %s_info;\n" + "\t\tg_type_add_interface_dynamic\n" + "\t\t\t( modinfo->instance_type\n" + "\t\t\t, modinfo->interface_type\n" + "\t\t\t, G_TYPE_PLUGIN(type_module)\n" + "\t\t\t);\n" + "\t\ttype_module->interface_infos = g_slist_prepend\n" + "\t\t\t( type_module->interface_infos\n" + "\t\t\t, modinfo\n" + "\t\t\t);\n", funcbase, type, name); g_free(type); g_free(name); diff --git a/tests/interface.at b/tests/interface.at index 82771e1..c8e2a9c 100644 --- a/tests/interface.at +++ b/tests/interface.at @@ -232,8 +232,6 @@ TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-b.o test-b-mod.o test-fooable.o main.o]) -# Currently borked -AT_XFAIL_IF([:]) AT_CHECK([./main], [0], [Test:A foo called 42 Test:B foo called @@ -286,8 +284,6 @@ TEST_COMPILE_GOBJECT([main.c], [0], [], [ignore]) AT_CHECK([$CC $CFLAGS $LDFLAGS $LIBGOBJECT_LIBS -o main \ test-a.o test-a-mod.o test-b.o test-b-mod.o test-fooable.o main.o]) -# Currently borked -AT_XFAIL_IF([:]) AT_CHECK([./main], [0], [Test:A foo called 42 Test:B foo called