Determine the suffix of the shared librarries for this system. This is

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

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

	* glib/glib-sections.txt: Added G_MODULE_SUFFIX.

	* glib/tmpl/modules.sgml: Updated.
This commit is contained in:
Sebastian Wilhelmi 2000-12-22 13:44:25 +00:00 committed by Sebastian Wilhelmi
parent 32241715f4
commit 57a7a2b010
21 changed files with 695 additions and 36 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -680,6 +680,21 @@ dnl *** done, have e got an implementation?
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)
@ -1499,6 +1514,8 @@ _______EOF
cat >>$outfile <<_______EOF
#define G_MODULE_SUFFIX "$g_module_suffix"
G_END_DECLS
#endif /* GLIBCONFIG_H */
@ -1709,6 +1726,8 @@ g_mutex_sizeof="$glib_cv_sizeof_gmutex"
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"

View File

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

View File

@ -1094,6 +1094,7 @@ g_module_error
<SUBSECTION>
GModuleCheckInit
GModuleUnload
G_MODULE_SUFFIX
G_MODULE_EXPORT
G_MODULE_IMPORT
</SECTION>

View File

@ -91,8 +91,20 @@ prefix and suffix. This should be freed when no longer needed.
<!-- ##### 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.
@ -183,6 +195,15 @@ It is passed the #GModule structure.
@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.

View File

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

View File

@ -71,13 +71,17 @@
/* --- 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
@ -88,7 +92,7 @@ _g_module_open (const gchar *file_name,
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;
}
@ -104,7 +108,7 @@ _g_module_self (void)
handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
if (!handle)
g_module_set_error (fetch_dlerror ());
g_module_set_error (fetch_dlerror (TRUE));
return handle;
}
@ -121,7 +125,7 @@ _g_module_close (gpointer handle,
if (is_unref)
{
if (dlclose (handle) != 0)
g_module_set_error (fetch_dlerror ());
g_module_set_error (fetch_dlerror (TRUE));
}
}
@ -133,7 +137,7 @@ _g_module_symbol (gpointer handle,
p = dlsym (handle, symbol_name);
if (!p)
g_module_set_error (fetch_dlerror ());
g_module_set_error (fetch_dlerror (FALSE));
return p;
}

View File

@ -28,11 +28,19 @@
* 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
@ -71,7 +79,6 @@ static inline GModule* g_module_find_by_name (const gchar *name);
/* --- variables --- */
G_LOCK_DEFINE_STATIC (GModule);
const char *g_log_domain_gmodule = "GModule";
static GModule *modules = NULL;
static GModule *main_module = NULL;
@ -85,7 +92,6 @@ g_module_find_by_handle (gpointer handle)
GModule *module;
GModule *retval = NULL;
G_LOCK (GModule);
if (main_module && main_module->handle == handle)
retval = main_module;
else
@ -95,7 +101,6 @@ g_module_find_by_handle (gpointer handle)
retval = module;
break;
}
G_UNLOCK (GModule);
return retval;
}
@ -106,14 +111,12 @@ g_module_find_by_name (const gchar *name)
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;
}
@ -177,6 +180,103 @@ g_module_supported (void)
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)
@ -186,9 +286,9 @@ g_module_open (const gchar *file_name,
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 ();
@ -203,8 +303,8 @@ g_module_open (const gchar *file_name,
main_module->next = NULL;
}
}
G_UNLOCK (GModule);
g_static_rec_mutex_unlock (&g_module_global_lock);
return main_module;
}
@ -214,11 +314,46 @@ g_module_open (const gchar *file_name,
{
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;
@ -233,6 +368,7 @@ g_module_open (const gchar *file_name,
module->ref_count++;
g_module_set_error (NULL);
g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
@ -245,10 +381,8 @@ g_module_open (const gchar *file_name,
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))
@ -273,7 +407,8 @@ g_module_open (const gchar *file_name,
g_free (saved_error);
}
g_static_rec_mutex_unlock (&g_module_global_lock);
return module;
}
@ -285,6 +420,8 @@ g_module_close (GModule *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)
@ -303,7 +440,6 @@ g_module_close (GModule *module)
last = NULL;
G_LOCK (GModule);
node = modules;
while (node)
{
@ -319,7 +455,6 @@ g_module_close (GModule *module)
node = last->next;
}
module->next = NULL;
G_UNLOCK (GModule);
_g_module_close (module->handle, FALSE);
g_free (module->file_name);
@ -327,6 +462,7 @@ g_module_close (GModule *module)
g_free (module);
}
g_static_rec_mutex_unlock (&g_module_global_lock);
return g_module_error() == NULL;
}
@ -359,6 +495,8 @@ g_module_symbol (GModule *module,
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;
@ -380,11 +518,10 @@ g_module_symbol (GModule *module,
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*

View File

@ -54,16 +54,9 @@ main (int arg,
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

View File

@ -6,6 +6,8 @@ Makefile.in
makefile.msc
makefile.mingw
_libs
libmoduletestplugin_a.la
libmoduletestplugin_b.la
array-test
date-test
dirname-test
@ -13,6 +15,7 @@ hash-test
list-test
mainloop-test
markup-test
module-test
node-test
queue-test
rand-test

View File

@ -20,6 +20,7 @@ test_programs = \
hash-test \
list-test \
mainloop-test \
module-test \
node-test \
queue-test \
rand-test \
@ -45,6 +46,7 @@ TESTS_ENVIRONMENT = srcdir=$(srcdir)
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)
@ -54,6 +56,8 @@ hash_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)
@ -68,6 +72,20 @@ threadpool_test_LDADD = $(thread_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

View File

@ -0,0 +1,68 @@
/* 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 ();
}

View File

@ -0,0 +1,67 @@
/* 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";
}

198
tests/module-test.c Normal file
View File

@ -0,0 +1,198 @@
/* 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;
}