+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * configure.in: Determine the suffix of the shared librarries for
+ this system. This is done analogous to
+ ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+ "sl", "dll", or (most often) "so".
+
+ * tests/Makefile.am, tests/module-test.c,
+ tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+ Added new testcase for gmodule. This is mostly copied from
+ gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+ some tests that verbose, not to say loquacious...)
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
if test -z "$G_MODULE_IMPL"; then
G_MODULE_IMPL=0
fi
+
+AC_MSG_CHECKING(for the suffix of shared libraries)
+case "$host_os" in
+ hpux9* | hpux10* | hpux11*) # taken from ltconfig
+ glib_gmodule_suffix='sl'
+ ;;
+ cygwin* | mingw*)
+ glib_gmodule_suffix='dll'
+ ;;
+ *)
+ glib_gmodule_suffix='so'
+ ;;
+esac
+AC_MSG_RESULT(.$glib_gmodule_suffix)
+
AC_SUBST(G_MODULE_IMPL)
AC_SUBST(G_MODULE_LIBS)
AC_SUBST(G_MODULE_LIBS_EXTRA)
cat >>$outfile <<_______EOF
+#define G_MODULE_SUFFIX "$g_module_suffix"
+
G_END_DECLS
#endif /* GLIBCONFIG_H */
g_system_thread_sizeof="$glib_cv_sizeof_system_thread"
g_mutex_contents="$glib_cv_byte_contents_gmutex"
+g_module_suffix="$glib_gmodule_suffix"
+
case $host in
*-*-beos*)
glib_os="#define G_OS_BEOS"
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * glib/glib-sections.txt: Added G_MODULE_SUFFIX.
+
+ * glib/tmpl/modules.sgml: Updated.
+
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* glib/glib-sections.txt: Added g_rand_boolean and
<SUBSECTION>
GModuleCheckInit
GModuleUnload
+G_MODULE_SUFFIX
G_MODULE_EXPORT
G_MODULE_IMPORT
</SECTION>
<!-- ##### FUNCTION g_module_open ##### -->
<para>
-Opens a module.
-If the module has already been opened, its reference count is incremented.
+Opens a module. If the module has already been opened, its reference
+count is incremented.
+</para>
+
+<para>
+First of all g_module_open() tries to open @file_name as a module. If
+that fails and @file_name has the ".la"-suffix (and is a libtool
+archive) it tries to open the corresponding module. If that fails and
+it doesn't have the proper module suffix for that plaform
+(#G_MODULE_SUFFIX,) this suffix will be appended and the coresponding
+module will be opended. If that fails and @file_name doesn't have the
+".la"-suffix, this suffix is appended and g_module_open() tries to
+open the corresponding module. If eventually that fails as well, NULL
+is returned.
</para>
@file_name: the name of the file containing the module.
@module: the module about to be unloaded.
+<!-- ##### MACRO G_MODULE_SUFFIX ##### -->
+<para>
+Expands to the proper shared library suffix for the current platform
+without the leading dot. For the most Unices and Linux this is "so",
+for some HPUX versions this is "sl" and for Windows this is "dll".
+</para>
+
+
+
<!-- ##### MACRO G_MODULE_EXPORT ##### -->
<para>
Used to declare functions exported by modules.
+2000-12-22 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
+
+ * gmodule.c: Make g_module_open more tolerant wrt to the module
+ name. First it tries to open the module as named, if that fails,
+ it checks, whether it is a libtool archive and parses it, if that
+ fails it appends the systems shared library suffix
+ (i.e. ".so") (if not already found) and tries again and if that
+ fails it tries to append the ".la" libtool suffix (if not already
+ found) and parses it.
+
+ * gmodule.c: Lock recursive mutex during most module functions for
+ safety.
+
+ * gmodule-dl.c: Return an error from _g_module_symbol only, if
+ dlerror says so. All other functions return an error as well, if
+ dlerror returns NULL.
+
+ * testgmodule.c: Thanks to the above change the #ifdefs have
+ vanished.
+
2000-10-15 Raja R Harinath <harinath@cs.umn.edu>
* Makefile.am (BUILT_EXTRA_DIST): New variable.
/* --- functions --- */
static gchar*
-fetch_dlerror (void)
+fetch_dlerror (gboolean replace_null)
{
gchar *msg = dlerror ();
- /* make sure we always return an error message != NULL */
+ /* make sure we always return an error message != NULL, if
+ * expected to do so. */
- return msg ? msg : "unknown dl-error";
+ if (!msg && replace_null)
+ return "unknown dl-error";
+
+ return msg;
}
static gpointer
handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
if (!handle)
- g_module_set_error (fetch_dlerror ());
+ g_module_set_error (fetch_dlerror (TRUE));
return handle;
}
handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
if (!handle)
- g_module_set_error (fetch_dlerror ());
+ g_module_set_error (fetch_dlerror (TRUE));
return handle;
}
if (is_unref)
{
if (dlclose (handle) != 0)
- g_module_set_error (fetch_dlerror ());
+ g_module_set_error (fetch_dlerror (TRUE));
}
}
p = dlsym (handle, symbol_name);
if (!p)
- g_module_set_error (fetch_dlerror ());
+ g_module_set_error (fetch_dlerror (FALSE));
return p;
}
* MT safe
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include "gmodule.h"
#include "gmoduleconf.h"
#include <errno.h>
#include <string.h>
-
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
/* We maintain a list of modules, so we can reference count them.
* That's needed because some platforms don't support refernce counts on
/* --- variables --- */
-G_LOCK_DEFINE_STATIC (GModule);
const char *g_log_domain_gmodule = "GModule";
static GModule *modules = NULL;
static GModule *main_module = NULL;
GModule *module;
GModule *retval = NULL;
- G_LOCK (GModule);
if (main_module && main_module->handle == handle)
retval = main_module;
else
retval = module;
break;
}
- G_UNLOCK (GModule);
return retval;
}
GModule *module;
GModule *retval = NULL;
- G_LOCK (GModule);
for (module = modules; module; module = module->next)
if (strcmp (name, module->file_name) == 0)
{
retval = module;
break;
}
- G_UNLOCK (GModule);
return retval;
}
return TRUE;
}
+static gchar*
+parse_libtool_archive (const gchar* libtool_name)
+{
+ const gint TOKEN_DLNAME = G_TOKEN_LAST + 1;
+ const gint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
+ const gint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
+ gchar *lt_dlname = NULL;
+ gboolean lt_installed = TRUE;
+ gchar *lt_libdir = NULL;
+ gchar *name;
+ GTokenType token;
+ GScanner *scanner;
+
+ int fd = open (libtool_name, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ g_module_set_error ("couldn't open libtool archive");
+ return NULL;
+ }
+ /* search libtool's dlname specification */
+ scanner = g_scanner_new (NULL);
+ g_scanner_input_file (scanner, fd);
+ scanner->config->symbol_2_token = TRUE;
+ g_scanner_scope_add_symbol (scanner, 0, "dlname",
+ GUINT_TO_POINTER (TOKEN_DLNAME));
+ g_scanner_scope_add_symbol (scanner, 0, "installed",
+ GUINT_TO_POINTER (TOKEN_INSTALLED));
+ g_scanner_scope_add_symbol (scanner, 0, "libdir",
+ GUINT_TO_POINTER (TOKEN_LIBDIR));
+ while (!g_scanner_eof (scanner))
+ {
+ token = g_scanner_get_next_token (scanner);
+ if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED ||
+ token == TOKEN_LIBDIR)
+ {
+ if (g_scanner_get_next_token (scanner) != '=' ||
+ g_scanner_get_next_token (scanner) !=
+ (token == TOKEN_INSTALLED ?
+ G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
+ {
+ g_module_set_error ("libtool archive has unknown format");
+
+ g_free (lt_dlname);
+ g_free (lt_libdir);
+ g_scanner_destroy (scanner);
+ close (fd);
+
+ return NULL;
+ }
+ else
+ {
+ if (token == TOKEN_DLNAME)
+ {
+ g_free (lt_dlname);
+ lt_dlname = g_strdup (scanner->value.v_string);
+ }
+ else if (token == TOKEN_INSTALLED)
+ lt_installed =
+ strcmp (scanner->value.v_identifier, "yes") == 0;
+ else /* token == TOKEN_LIBDIR */
+ {
+ g_free (lt_libdir);
+ lt_libdir = g_strdup (scanner->value.v_string);
+ }
+ }
+ }
+ }
+
+ if (!lt_installed)
+ {
+ gchar *dir = g_path_get_dirname (libtool_name);
+ g_free (lt_libdir);
+ lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL);
+ }
+
+ name = g_module_build_path (lt_libdir, lt_dlname);
+
+ g_free (lt_dlname);
+ g_free (lt_libdir);
+ g_scanner_destroy (scanner);
+ close (fd);
+
+ return name;
+}
+
+static inline gboolean
+g_str_check_suffix (const gchar* string, const gchar* suffix)
+{
+ guint string_len = strlen (string);
+ guint suffix_len = strlen (suffix);
+
+ return string_len >= suffix_len &&
+ strcmp (string + string_len - suffix_len, suffix) == 0;
+}
+
+static GStaticRecMutex g_module_global_lock = G_STATIC_REC_MUTEX_INIT;
+
GModule*
g_module_open (const gchar *file_name,
GModuleFlags flags)
SUPPORT_OR_RETURN (NULL);
+ g_static_rec_mutex_lock (&g_module_global_lock);
if (!file_name)
{
- G_LOCK (GModule);
if (!main_module)
{
handle = _g_module_self ();
main_module->next = NULL;
}
}
- G_UNLOCK (GModule);
+ g_static_rec_mutex_unlock (&g_module_global_lock);
return main_module;
}
{
module->ref_count++;
+ g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
- /* open the module */
+ /* First we try to open the module as provided */
handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
+
+ /* If not found, we check, if it is a libtool archive */
+ if (!handle && g_str_check_suffix (file_name, ".la"))
+ {
+ gchar *name = parse_libtool_archive (file_name);
+ if (name)
+ {
+ handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+ g_free (name);
+ }
+ }
+
+ /* If still not found, we check, if it is a library name without suffix */
+ if (!handle && !g_str_check_suffix (file_name, "." G_MODULE_SUFFIX))
+ {
+ gchar *name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
+ handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+ g_free (name);
+ }
+
+ /* If still not found, we check, if it is a libtool archive name
+ * without suffix */
+ if (!handle && !g_str_check_suffix (file_name, ".la"))
+ {
+ gchar *la_name = g_strconcat (file_name, ".la", NULL);
+ gchar *name = parse_libtool_archive (la_name);
+ if (name)
+ {
+ handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+ g_free (name);
+ }
+ g_free (la_name);
+ }
+
if (handle)
{
gchar *saved_error;
module->ref_count++;
g_module_set_error (NULL);
+ g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
module->ref_count = 1;
module->is_resident = FALSE;
module->unload = NULL;
- G_LOCK (GModule);
module->next = modules;
modules = module;
- G_UNLOCK (GModule);
/* check initialization */
if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
g_free (saved_error);
}
-
+
+ g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
g_return_val_if_fail (module != NULL, FALSE);
g_return_val_if_fail (module->ref_count > 0, FALSE);
+ g_static_rec_mutex_lock (&g_module_global_lock);
+
module->ref_count--;
if (!module->ref_count && !module->is_resident && module->unload)
last = NULL;
- G_LOCK (GModule);
node = modules;
while (node)
{
node = last->next;
}
module->next = NULL;
- G_UNLOCK (GModule);
_g_module_close (module->handle, FALSE);
g_free (module->file_name);
g_free (module);
}
+ g_static_rec_mutex_unlock (&g_module_global_lock);
return g_module_error() == NULL;
}
g_return_val_if_fail (symbol_name != NULL, FALSE);
g_return_val_if_fail (symbol != NULL, FALSE);
+ g_static_rec_mutex_lock (&g_module_global_lock);
+
#ifdef G_MODULE_NEED_USCORE
{
gchar *name;
g_module_set_error (error);
g_free (error);
*symbol = NULL;
-
- return FALSE;
}
- return TRUE;
+ g_static_rec_mutex_unlock (&g_module_global_lock);
+ return !module_error;
}
gchar*
string = g_get_current_dir ();
g_print ("testgmodule (%s):\n", string);
-#if (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
- plugin_a = g_strconcat (string, "\\libgplugin_a.dll", NULL);
- plugin_b = g_strconcat (string, "\\libgplugin_b.dll", NULL);
-#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
- plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.sl", NULL);
- plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.sl", NULL);
-#else /* neither DLD nor WIN32 */
- plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.so", NULL);
- plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.so", NULL);
-#endif
+ plugin_a = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_a", NULL);
+ plugin_b = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_b", NULL);
+
g_free (string);
/* module handles
makefile.msc
makefile.mingw
_libs
+libmoduletestplugin_a.la
+libmoduletestplugin_b.la
array-test
date-test
dirname-test
list-test
mainloop-test
markup-test
+module-test
node-test
queue-test
rand-test
hash-test \
list-test \
mainloop-test \
+ module-test \
node-test \
queue-test \
rand-test \
progs_LDADD = $(EFENCE) $(top_builddir)/libglib-1.3.la $(EFENCE)
thread_LDADD = $(progs_LDADD) $(top_builddir)/gthread/libgthread-1.3.la @G_THREAD_LIBS@
+module_LDADD = $(progs_LDADD) $(top_builddir)/gmodule/libgmodule-1.3.la @G_MODULE_LIBS@
array_test_LDADD = $(progs_LDADD)
date_test_LDADD = $(progs_LDADD)
list_test_LDADD = $(progs_LDADD)
mainloop_test_LDADD = $(thread_LDADD)
markup_test_LDADD = $(progs_LDADD)
+module_test_LDADD = $(module_LDADD)
+module_test_LDFLAGS = @G_MODULE_LDFLAGS@
node_test_LDADD = $(progs_LDADD)
queue_test_LDADD = $(progs_LDADD)
rand_test_LDADD = $(progs_LDADD)
tree_test_LDADD = $(progs_LDADD)
type_test_LDADD = $(progs_LDADD)
+lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la
+
+# Prevent those libs from being installed
+install-libLTLIBRARIES:
+ :
+
+libmoduletestplugin_a_la_SOURCES = libmoduletestplugin_a.c
+libmoduletestplugin_a_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module
+libmoduletestplugin_a_la_LIBADD = @G_MODULE_LIBS@
+
+libmoduletestplugin_b_la_SOURCES = libmoduletestplugin_b.c
+libmoduletestplugin_b_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module
+libmoduletestplugin_b_la_LIBADD = @G_MODULE_LIBS@
+
makefile.msc: $(top_builddir)/config.status $(top_srcdir)/tests/makefile.msc.in
cd $(top_builddir) && CONFIG_FILES=tests/$@ CONFIG_HEADERS= $(SHELL) ./config.status
--- /dev/null
+/* libgplugin_a.c - test plugin for testgmodule
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <gmodule.h>
+#include <stdlib.h>
+
+G_MODULE_EXPORT gchar* gplugin_a_state;
+
+G_MODULE_EXPORT void
+gplugin_a_func (void)
+{
+ gplugin_a_state = "Hello world";
+}
+
+G_MODULE_EXPORT void
+gplugin_clash_func (void)
+{
+ gplugin_a_state = "plugin clash";
+}
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+ gplugin_a_state = "global clash";
+}
+
+G_MODULE_EXPORT void
+gplugin_say_boo_func (void)
+{
+ gplugin_a_state = "BOOH";
+}
+
+G_MODULE_EXPORT void
+gplugin_a_module_func (GModule *module)
+{
+ void (*f) (void) = NULL;
+
+ if (!g_module_symbol (module, "gplugin_say_boo_func", (gpointer) &f))
+ {
+ g_print ("error: %s\n", g_module_error ());
+ exit (1);
+ }
+
+ f ();
+}
--- /dev/null
+/* libgplugin_b.c - test plugin for testgmodule
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <gmodule.h>
+
+G_MODULE_EXPORT gchar* gplugin_b_state;
+
+G_MODULE_EXPORT const gchar*
+g_module_check_init (GModule *module)
+{
+ gplugin_b_state = "check-init";
+
+ return NULL;
+}
+
+G_MODULE_EXPORT void
+g_module_unload (GModule *module)
+{
+ gplugin_b_state = "unloaded";
+}
+
+G_MODULE_EXPORT void
+gplugin_b_func (void)
+{
+ gplugin_b_state = "Hello world";
+}
+
+G_MODULE_EXPORT void
+gplugin_clash_func (void)
+{
+ gplugin_b_state = "plugin clash";
+}
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+ gplugin_b_state = "global clash";
+}
+
+G_MODULE_EXPORT void
+gplugin_say_boo_func (void)
+{
+ gplugin_b_state = "BOOH";
+}
--- /dev/null
+/* module-test.c - test program for GMODULE
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <gmodule.h>
+
+gchar* global_state;
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+ global_state = "global clash";
+}
+
+typedef void (*SimpleFunc) (void);
+typedef void (*GModuleFunc) (GModule *);
+
+static gchar **gplugin_a_state;
+static gchar **gplugin_b_state;
+
+static void
+compare (const gchar *desc, const gchar *expected, const gchar *found)
+{
+ if (!expected && !found)
+ return;
+
+ if (expected && found && strcmp (expected, found) == 0)
+ return;
+
+ g_error ("error: %s state should have been \"%s\", but is \"%s\"",
+ desc, expected ? expected : "NULL", found ? found : "NULL");
+}
+
+static void
+test_states (const gchar *global, const gchar *gplugin_a,
+ const gchar *gplugin_b)
+{
+ compare ("global", global, global_state);
+ compare ("Plugin A", gplugin_a, *gplugin_a_state);
+ compare ("Plugin B", gplugin_b, *gplugin_b_state);
+
+ global_state = *gplugin_a_state = *gplugin_b_state = NULL;
+}
+
+static SimpleFunc plugin_clash_func = NULL;
+
+int
+main (int arg,
+ char *argv[])
+{
+ GModule *module_self, *module_a, *module_b;
+ gchar *dir;
+ gchar *plugin_a, *plugin_b;
+ SimpleFunc f_a, f_b, f_self;
+ GModuleFunc gmod_f;
+
+ if (!g_module_supported ())
+ return 0;
+
+ dir = g_get_current_dir ();
+
+ plugin_a = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_a",
+ NULL);
+ plugin_b = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_b",
+ NULL);
+
+ g_free (dir);
+
+ /* module handles */
+
+ module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
+ if (!module_self)
+ g_error ("error: %s", g_module_error ());
+
+ if (!g_module_symbol (module_self, "g_module_close", (gpointer) &f_self))
+ g_error ("error: %s", g_module_error ());
+
+ module_a = g_module_open (plugin_a, G_MODULE_BIND_LAZY);
+ if (!module_a)
+ g_error ("error: %s", g_module_error ());
+
+ module_b = g_module_open (plugin_b, G_MODULE_BIND_LAZY);
+ if (!module_b)
+ g_error ("error: %s", g_module_error ());
+
+ /* get plugin state vars */
+
+ if (!g_module_symbol (module_a, "gplugin_a_state",
+ (gpointer) &gplugin_a_state))
+ g_error ("error: %s", g_module_error ());
+
+ if (!g_module_symbol (module_b, "gplugin_b_state",
+ (gpointer) &gplugin_b_state))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, "check-init");
+
+ /* get plugin specific symbols and call them
+ */
+ if (!g_module_symbol (module_a, "gplugin_a_func", (gpointer) &f_a))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ if (!g_module_symbol (module_b, "gplugin_b_func", (gpointer) &f_b))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ f_a ();
+ test_states (NULL, "Hello world", NULL);
+
+ f_b ();
+ test_states (NULL, NULL, "Hello world");
+
+ /* get and call globally clashing functions
+ */
+
+ if (!g_module_symbol (module_self, "g_clash_func", (gpointer) &f_self))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ if (!g_module_symbol (module_a, "g_clash_func", (gpointer) &f_a))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ if (!g_module_symbol (module_b, "g_clash_func", (gpointer) &f_b))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ f_self ();
+ test_states ("global clash", NULL, NULL);
+
+ f_a ();
+ test_states (NULL, "global clash", NULL);
+
+ f_b ();
+ test_states (NULL, NULL, "global clash");
+
+ /* get and call clashing plugin functions */
+
+ if (!g_module_symbol (module_a, "gplugin_clash_func", (gpointer) &f_a))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ if (!g_module_symbol (module_b, "gplugin_clash_func", (gpointer) &f_b))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ plugin_clash_func = f_a;
+ plugin_clash_func ();
+ test_states (NULL, "plugin clash", NULL);
+
+ plugin_clash_func = f_b;
+ plugin_clash_func ();
+ test_states (NULL, NULL, "plugin clash");
+
+ /* call gmodule function from A */
+
+ if (!g_module_symbol (module_a, "gplugin_a_module_func", (gpointer) &gmod_f))
+ g_error ("error: %s", g_module_error ());
+ test_states (NULL, NULL, NULL);
+
+ gmod_f (module_b);
+ test_states (NULL, NULL, "BOOH");
+
+ gmod_f (module_a);
+ test_states (NULL, "BOOH", NULL);
+
+ /* unload plugins */
+
+ if (!g_module_close (module_a))
+ g_error ("error: %s", g_module_error ());
+
+ if (!g_module_close (module_b))
+ g_error ("error: %s", g_module_error ());
+
+ return 0;
+}