Re: revised patch for glib compilation
- From: Gary V.Vaughan <gvv techie com>
- To: timj gtk org
- Cc: gtk-devel-list gnome org
- Subject: Re: revised patch for glib compilation
- Date: Sat, 24 Feb 2001 23:40:08 +0000
Hi Tim,
Please excuse the mangled Reference:s, I lost my mail archive along with most
of the contents of my hard drive a few weeks ago, so I replied to the oldest
message I have left in the thread...
Anyway, I redid my implementation of gmodule as a wrapper for libltdl to take
advantage of the thread locking hooks just committed to libtool CVS, so that
we can hopefully unify the two code bases. The last few months have occupied
me with pushing features gmodule had down into libltdl to make this possible,
so the wrapper is actually very thin.
The purpose of this mail is mainly to get some feedback -- I haven't actually
tested the code at all. In fact, I have never programmed with threads in C
before, so some pointers to a small threaded gmodule using project would be a
huge help!
Let me know what you think and if you approve I will incorporate any
suggestions you have, clean the whole thing up and resubmit.
Cheers,
Gary.
--
___ _ ___ __ _ mailto: gvv techie com
/ __|__ _ _ ___ _| | / / | / /_ _ _ _ __ _| |_ __ _ ___ gary gnu org
| (_ / _` | '_|// / |/ /| |/ / _` | || / _` | ' \/ _` | _ \
\___\__,_|_|\_, /|___(_)___/\__,_|\_,_\__, |_||_\__,_|//_/
home page: /___/ /___/ gpg public key:
http://www.oranda.demon.co.uk http://www.oranda.demon.co.uk/key.asc
/* GMODULE - GLIB wrapper code for dynamic module loading
* 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 "gmoduleconf.h"
#include "ltdl.h"
#include <errno.h>
#include <string.h>
#define G_CALLERID_UNDEFINED ((lt_dlcaller_id) -1)
#define G_MODULE_INI_STRING "g_module_check_init"
#define G_MODULE_FINI_STRING "g_module_unload"
/* --- prototypes --- */
static inline gboolean g_module_init_once (void);
static inline void g_module_set_error (const gchar *error);
static const gchar *g_module_get_error (void);
static void g_module_mutex_lock (void);
static void g_module_mutex_unlock (void);
/* --- variables --- */
G_LOCK_DEFINE_STATIC (GModule);
const char *g_log_domain_gmodule = "GModule";
static GStaticPrivate module_error_private = G_STATIC_PRIVATE_INIT;
/* --- inline functions --- */
static inline void
g_module_set_error (const gchar *error)
{
g_static_private_set (&module_error_private, error, NULL);
errno = 0;
}
/* For orthogonality only: g_module_error already does exactly what
is required, but is named according to the supported API. */
#define g_module_get_error g_module_error
static inline gboolean
g_module_init_once (void)
{
static gint initialized = 0;
/* Clear error message for this thread. */
g_module_set_error (NULL);
G_LOCK (GModule);
if (++initialized == 1)
{
gint errors = 0; /* Number of errors from libltdl calls. */
/* Make sure libltdl is using our memory managment API. */
lt_dlmalloc = (lt_ptr(*)(size_t)) g_malloc;
lt_dlfree = (void (*)(lt_ptr)) g_free;
/* Register the callbacks to make all lt_*() functions MT safe. */
lt_dlmutex_register (g_module_mutex_lock, g_module_mutex_unlock,
g_module_set_error, g_module_get_error);
/* Initialise ltdl library. */
errors = lt_dlinit ();
if (!errors)
{
gchar *path = g_getenv ("GMODULE_PATH");
/* Create a gmodule specific key for subsequent access to
per-module data stored by gmodule functions. */
g_module_caller_id = lt_dlcaller_register ();
/* Initialise libltdl module search directory list. */
if (path != NULL)
errors = lt_dladdsearchdir (path);
}
G_UNLOCK (GModule);
return (errors == 0);
}
G_UNLOCK (GModule);
return TRUE;
}
/* --- static functions --- */
static void
g_module_mutex_lock (void)
{
G_LOCK (GModule);
}
static void
g_module_mutex_unlock (void)
{
G_UNLOCK (GModule);
}
/* --- exported functions --- */
/**
* g_module_supported:
*
* This function is deprecated.
* Check if modules are supported on the current platform. Now that
* the gmodule API is a wrapper for libltdl, this function will always
* return %TRUE.
*
* Return value: %TRUE if modules are supported.
**/
gboolean
g_module_supported (void)
{
#if G_ENABLE_DEBUG
static gboolean first_call = TRUE;
if (first_call)
{
g_warning ("g_module_supported is deprecated.");
g_warning ("modules are always supported by the underlying libltdl.");
first_call = FALSE;
}
#endif /* G_ENABLE_DEBUG */
return TRUE;
}
/**
* g_module_open:
* @filename: the name of the file containing the module to be opened.
* @flags: not used.
*
* Opens a module. If the module has already been opened, its reference
* count is incremented.
*
* 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 @file_name
* doesn't have the proper module suffix for the host platform, this suffix
* will be appended and any corresponding module opened. If that fails and
* @file_name doesn't have the ".la"-suffix, it is appended and
* g_module_open() tries to open the corresponding module. If ultimately
* that fails as well, %NULL is returned.
*
* Return value: a #GModule on success, or %NULL on failure.
**/
GModule*
g_module_open (const gchar *file_name,
GModuleFlags flags)
{
lt_dlhandle handle = (lt_dlhandle) 0;
g_module_init_once ();
/* open the module */
handle = lt_dlopenext (file_name);
if (handle)
{
gchar *error = NULL;
GModuleCheckInit check_init;
GModuleUnload unload;
const gchar *check_failed_error = NULL;
/* check initialization */
if (g_module_symbol ((GModule *) handle, G_MODULE_INI_STRING,
(gpointer) &check_init))
{
check_failed_error = check_init ((GModule *) handle);
}
if (check_failed_error != NULL)
{
error = g_strconcat ("GModule initialization check failed: ",
check_failed_error, NULL);
}
/* Register error diagnostic generated above, if any. */
if (error)
{
g_module_close ((GModule *) handle);
module = NULL;
g_module_set_error (error);
g_free (error);
}
}
return module;
}
/**
* g_module_close:
* @module: the module to be closed.
*
* Closes an open module.
*
* Return value: %TRUE on success.
**/
gboolean
g_module_close (GModule *module)
{
lt_dlinfo *info;
gboolean success = TRUE;
g_return_val_if_fail (module != NULL, FALSE);
g_module_init_once (); /* Is this really neccessary? */
info = lt_dlgetinfo ((lt_dlhandle) module);
g_return_val_if_fail (info->ref_count > 1, FALSE);
if ((info->ref_count == 1) && !lt_dlisresident ((lt_dlhandle) module))
{
GModuleUnload unload;
lt_ptr stale = NULL;
unload = g_module_symbol (module, G_MODULE_FINI_STRING,
(gpointer) &unload);
if (unload)
unload (module);
if (lt_dlclose ((lt_dlhandle) module) != 0)
success = FALSE;
g_free (module);
}
return success;
}
/**
* g_module_make_resident:
* @module: the module to make permenantly resident.
*
* Ensures that a module can never be unloaded. Any future g_module_close()
* calls on the module will have no effect. If you open the entire process
* as a reflexive module, then it is always made resident by default -- there
* is no need to call this function manually.
**/
void
g_module_make_resident (GModule *module)
{
g_return_if_fail (module != NULL);
lt_dlmakeresident ((lt_dlhandle) module);
}
/**
* g_module_error:
*
* Get a string describing the last error that occured in the gmodule
* subsystem.
*
* Return value: a string describing the last module error.
**/
gchar*
g_module_error (void)
{
return g_static_private_get (&module_error_private);
}
/**
* g_module_symbol:
* @module: the module.
* @symbol_name: the name of the symbol to find.
* @symbol: returns the pointer to the symbol value.
*
* Gets a symbol pointer from a module.
*
* Return value: %TRUE on success.
**/
gboolean
g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer *symbol)
{
if (symbol)
*symbol = NULL;
g_return_val_if_fail (module != NULL, FALSE);
g_return_val_if_fail (symbol_name != NULL, FALSE);
g_return_val_if_fail (symbol != NULL, FALSE);
*symbol = lt_dlsym ((lt_dlhandle) module, symbol_name);
if (*symbol == NULL)
{
gchar *module_error = lt_dlerror ();
gchar *error;
error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
g_module_set_error (error);
g_free (error);
return FALSE;
}
return TRUE;
}
/**
* g_module_name:
* @module: the module.
*
* Gets the file name from a #GModule.
*
* Return value: the file name of the module, or "main" if the module
* is the main program itself.
**/
gchar*
g_module_name (GModule *module)
{
lt_dlinfo *info;
g_return_val_if_fail (module != NULL, NULL);
info = lt_dlgetinfo ((lt_dlhandle) module);
return g_strdup (info->filename ? info->filename : "main");
}
/**
* g_module_set_search_path:
* @path: a colon delimited list of directories.
*
* Set the paths of the directories to be searced when trying to
* locate a module opened using a relative path.
*
* Return value: %TRUE if successful.
**/
gboolean
g_module_set_search_path (gchar *path)
{
return (lt_dlsetsearchpath (path) == 0);
}
/**
* g_module_add_search_path:
* @path: a colon delimited list of directories.
*
* Append to the list of user paths, the additional @path of directories
* to be searched when trying to locate a module opened using a
* relative path.
*
* Return value: %TRUE if successful.
**/
gboolean
g_module_add_search_path (gchar *path)
{
return (lt_dladdsearchdir (path) == 0);
}
/**
* g_module_build_path:
* @directory: the directory where the module is.
* @module_name: the name of the module.
*
* This function is deprecated.
**/
gchar*
g_module_build_path (const gchar *directory,
const gchar *module_name)
{
#if G_ENABLE_DEBUG
static gboolean first_call = TRUE;
if (first_call)
{
g_warning ("g_module_build_path is deprecated.");
g_warning ("Use g_module_set_search_path or g_module_add_search_path.");
first_call = FALSE;
}
#endif /* G_ENABLE_DEBUG */
#if (G_MODULE_IMPL == G_MODULE_IMPL_DL)
if (directory && *directory) {
if (strncmp (module_name, "lib", 3) == 0)
return g_strconcat (directory, "/", module_name, NULL);
else
return g_strconcat (directory, "/lib", module_name, ".so", NULL);
} else if (strncmp (module_name, "lib", 3) == 0)
return g_strdup (module_name);
else
return g_strconcat ("lib", module_name, ".so", NULL);
#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
if (directory && *directory)
if (strncmp (module_name, "lib", 3) == 0)
return g_strconcat (directory, "/", module_name, NULL);
else
return g_strconcat (directory, "/lib", module_name, ".sl", NULL);
else if (strncmp (module_name, "lib", 3) == 0)
return g_strdup (module_name);
else
return g_strconcat ("lib", module_name, ".sl", NULL);
#elif (G_MODULE_IMPL == G_MODULE_IMPL_BEOS)
g_warning ("g_module_build_path() untested for BeOS!");
if (directory && *directory)
{
if (strncmp (module_name, "lib", 3) == 0)
return g_strconcat (directory, "/", module_name, NULL);
else
return g_strconcat (directory, "/lib", module_name, ".so", NULL);
}
else if (strncmp (module_name, "lib", 3) == 0)
return g_strdup (module_name);
else
return g_strconcat ("lib", module_name, ".so", NULL);
#elif (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
{
gint k = strlen (module_name);
if (directory && *directory)
if (k > 4 && g_strcasecmp (module_name + k - 4, ".dll") == 0)
return g_strconcat (directory, "\\", module_name, NULL);
else
return g_strconcat (directory, "\\", module_name, ".dll", NULL);
else if (k > 4 && g_strcasecmp (module_name + k - 4, ".dll") == 0)
return g_strdup (module_name);
else
return g_strconcat (module_name, ".dll", NULL);
}
#elif (G_MODULE_IMPL == G_MODULE_IMPL_OS2)
{
gchar *suffix = strrchr(module_name, '.');
if (directory && *directory)
if (suffix && (stricmp (suffix, ".dll") == 0))
return g_strconcat (directory, "/", module_name, NULL);
else
return g_strconcat (directory, "/", module_name, ".dll", NULL);
else if (suffix && (stricmp (suffix, ".dll") == 0))
return g_strdup (module_name);
else
return g_strconcat (module_name, ".dll", NULL);
}
#endif
return NULL;
}
/* GMODULE - GLIB wrapper code for dynamic module loading
* 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/.
*/
#ifndef __GMODULE_H__
#define __GMODULE_H__
extern const char *g_log_domain_gmodule;
#include <glib.h>
G_BEGIN_DECLS
/* exporting and importing functions, this is special cased
* to feature Windows dll stubs.
*/
#define G_MODULE_IMPORT extern
#if defined (G_OS_WIN32)
# define G_MODULE_EXPORT __declspec(dllexport)
#else /* !G_OS_WIN32 */
# define G_MODULE_EXPORT
#endif /* !G_OS_WIN32 */
/* No longer used. These remain for interface compatibility only. */
typedef enum
{
G_MODULE_BIND_LAZY = 1 << 0,
G_MODULE_BIND_MASK = 0x01
} GModuleFlags;
typedef gpointer GModule;
typedef const gchar* (*GModuleCheckInit) (GModule *module);
typedef void (*GModuleUnload) (GModule *module);
/* open a module `file_name' and return handle, which is NULL on error */
GModule* g_module_open (const gchar *file_name,
GModuleFlags flags);
/* close a previously opened module, returns TRUE on success */
gboolean g_module_close (GModule *module);
/* make a module resident so g_module_close on it will be ignored */
void g_module_make_resident (GModule *module);
/* query the last module error as a string */
gchar* g_module_error (void);
/* retrive a symbol pointer from `module', returns TRUE on success */
gboolean g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer *symbol);
/* retrive the file name from an existing module */
gchar* g_module_name (GModule *module);
/* Reset the list of colon separated module search directories. */
gchar* g_module_set_search_path (gchar *path);
/* Add a new search directory to the list. */
gchar* g_module_add_search_path (gchar *path);
/* --- deprecated functions --- */
gboolean g_module_supported (void) G_GNUC_CONST;
gchar* g_module_build_path (const gchar *directory,
const gchar *module_name);
G_END_DECLS
#endif /* __GMODULE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]