From fc2b1937c83db15c74384c564f8199ba527c7ba7 Mon Sep 17 00:00:00 2001 From: "Gary V. Vaughan" Date: Thu, 15 Jul 2004 12:37:15 +0000 Subject: [PATCH] * libltdl/lt__private.h (lt_dlhandle_struct): Renamed to lt__handle to better reflect the naming scheme. * libltdl/ltdl.h (lt_dlhandle): Be truly opaque with a void *. * libltdl/lt_dlloader.c (lt_dlloader_remove): Party to lt__private.h, so use internal lt__handle instead of opaque lt_dlhandle. * libltdl/ltdl.c (LT_DLGET_FLAG, LT_DLSET_FLAG): Add a cast to internal lt__handle type. (try_dlopen, tryall_dlopen, load_deplibs, unload_deplibs): Ditto. (lt_dlexit, lt_dlclose, lt_dlsym): Use lt__handle to iterate throught the handle list. (try_dlopen): Use lt__zalloc instead of MALLOC and memset. * libltdl/ltdl.h (lt_dlcaller_id): Be truly opaque with a void *. (lt_dlhandle_interface): New callback type for filtering handles according to the interface they present. * libltdl/ltdl.c (lt_dlcaller_register): Take an id and an interface check callback, and generate a caller_id. (iterator): New static variable for the use of... (lt_dlhandle_first): New function. Set the iterator for subsequent calls to lt_dlhandle_next. (lt_dlhandle_next): Either work as before when iterator is unset, or else skip handles that fail the interface check in iterator set by lt_dlhandle_first. * libltdl/ltdl.h (lt_dlhandle_first): Declaration. * doc/libtool.texi (User defined module data): Document the new APIs. * NEWS: Updated. --- ChangeLog | 30 +++++ NEWS | 2 + doc/libtool.texi | 69 +++++++++- libltdl/lt__private.h | 6 +- libltdl/lt_dlloader.c | 4 +- libltdl/ltdl.c | 304 +++++++++++++++++++++++++----------------- libltdl/ltdl.h | 23 ++-- 7 files changed, 300 insertions(+), 138 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7c3a094b7..d8b6dd97a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2004-07-15 Gary V. Vaughan + + * libltdl/lt__private.h (lt_dlhandle_struct): Renamed to + lt__handle to better reflect the naming scheme. + * libltdl/ltdl.h (lt_dlhandle): Be truly opaque with a void *. + * libltdl/lt_dlloader.c (lt_dlloader_remove): Party to + lt__private.h, so use internal lt__handle instead of opaque + lt_dlhandle. + * libltdl/ltdl.c (LT_DLGET_FLAG, LT_DLSET_FLAG): Add a cast to + internal lt__handle type. + (try_dlopen, tryall_dlopen, load_deplibs, unload_deplibs): Ditto. + (lt_dlexit, lt_dlclose, lt_dlsym): Use lt__handle to iterate + throught the handle list. + (try_dlopen): Use lt__zalloc instead of MALLOC and memset. + * libltdl/ltdl.h (lt_dlcaller_id): Be truly opaque with a void *. + (lt_dlhandle_interface): New callback type for filtering handles + according to the interface they present. + * libltdl/ltdl.c (lt_dlcaller_register): Take an id and an + interface check callback, and generate a caller_id. + (iterator): New static variable for the use of... + (lt_dlhandle_first): New function. Set the iterator for + subsequent calls to lt_dlhandle_next. + (lt_dlhandle_next): Either work as before when iterator is unset, + or else skip handles that fail the interface check in iterator set + by lt_dlhandle_first. + * libltdl/ltdl.h (lt_dlhandle_first): Declaration. + * doc/libtool.texi (User defined module data): Document the new + APIs. + * NEWS: Updated. + 2004-07-15 Gary V. Vaughan Split lt_dlloader management into a separate file, and factor diff --git a/NEWS b/NEWS index 8631f069a..3e3ea5a7f 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,8 @@ New in 1.5b: 2004-??-??; CVS version 1.5a, Libtool team: * libltdl no longer loads shared libraries with global symbol resolution, this caused problems when the symbols were intended to be overriden further up the stack; it is also not recommended practice. +* New function in libltdl: lt_dlhandle_first, primes handle iterations (using + lt_dlhandle_next) to filter by module interface. * libltdl no longer tries to support multi-threaded programming with lt_dlmutex_register(), which was unusable with POSIX threads anyway. The symbols are deprecated but exported for backwards compatibility. diff --git a/doc/libtool.texi b/doc/libtool.texi index efc6b0442..03874cf0d 100644 --- a/doc/libtool.texi +++ b/doc/libtool.texi @@ -3430,6 +3430,15 @@ Iterate over the loaded module handles, returning the first handle in the list if @var{place} is @code{NULL}, and the next one on subsequent calls. If @var{place} is the last element in the list of loaded modules, this function returns @code{NULL}. + +@example + lt_dlhandle handle = 0; + + while ((handle = lt_dlhandle_next (handle))) + @{ + @dots{} + @} +@end example @end deftypefun @deftypefun lt_dlhandle lt_dlhandle_find (@w{const char *@var{module_name}}) @@ -3451,8 +3460,17 @@ own data against loaded modules, without interfering with one another. The opaque type used to hold individual data set keys. @end deftp -@deftypefun lt_dlcaller_id lt_dlcaller_register (void) -Use this to obtain a unique key to store and retrieve per module data. +@deftp {Type} int lt_dlhandle_interface (@w{lt_dlhandle @var{handle},} @w{const char *@var{id_string}}) +Functions of this type are called to check that a handle conforms to a +library's expected module interface when iterating over the global +handle list. +@end deftp + +@deftypefun lt_dlcaller_id lt_dlcaller_register (@w{const char *@var{id_string},} @w{lt_dlhandle_interface *@var{iface}}) +Use this to obtain a unique key to store and retrieve per module data, +if you supply an @var{id_string} and @var{iface}, then the resulting +@code{lt_dlcaller_id} can be used to filter the module handles +returned by @samp{lt_dlhandle_next}. @end deftypefun @deftypefun lt_ptr lt_dlcaller_set_data (@w{lt_dlcaller_id @var{key}}, @w{lt_dlhandle @var{handle}}, @w{lt_ptr @var{data}}) @@ -3510,6 +3528,53 @@ my_dlcaller_foreach (lt_dlcaller_id key) @} @end example +@deftypefun lt_dlhandle lt_dlhandle_first (@w{lt_dlcaller_id @var{key}}) +Normally, you can fetch each of the loaded module handles in turn with +successive calls to @samp{lt_dlhandle_next} as shown in the example +above. In that example, the loop iterates over every libltdl loaded +module in your application, including the modules used by libltdl +itself! This is useful from within a module loader for example. + +@noindent +Often, your application doesn't want to concern itself with modules +loaded by the libraries it uses, or for libltdl's internal use. In +order to do that, you need to specify an interface validator callback: + +@example +/* @r{Return non-zero if} @var{handle} @r{doesn't conform to my iface.} */ +int +iface_validator_callback (lt_dlhandle handle, const char *id_string) +@{ + return (lt_sym (handle, "module_entry_point") != 0) +@} +@end example + +@noindent +When you register for a caller identification with +@samp{lt_dlcaller_register}, you log the interface validator. But +this time, when you start the iterator loop over the loaded module +handles, if you fetch the first handle with @samp{lt_dlhandle_first}, +then that and all subsequent calls to @samp{lt_dlhandle_next} will +skip any loaded module handles that fail the registered interface +validator callback function: + +@example + /* @r{Register for a} caller_id @r{to identify ourselves to} libltdl. */ + caller_id = lt_dlcaller_register ("example", iface_validator_callback); + +@dots{} + /* @r{Iterate over the modules related to my} caller_id. */ + @{ + lt_dlhandle handle = lt_dlhandle_first (caller_id); + + while ((handle = lt_dlhandle_next (handle))) + @{ + @dots{} + @} + @} +@end example +@end deftypefun + @node Module loaders for libltdl @section How to create and register new module loaders diff --git a/libltdl/lt__private.h b/libltdl/lt__private.h index 90734dccb..258033e90 100644 --- a/libltdl/lt__private.h +++ b/libltdl/lt__private.h @@ -97,8 +97,10 @@ typedef struct { void * data; } lt_caller_data; -struct lt_dlhandle_struct { - struct lt_dlhandle_struct *next; +typedef struct lt__handle lt__handle; + +struct lt__handle { + lt__handle * next; const lt_dlvtable * vtable; /* dlopening interface */ lt_dlinfo info; /* user visible fields */ int depcount; /* number of dependencies */ diff --git a/libltdl/lt_dlloader.c b/libltdl/lt_dlloader.c index e4d9195b3..714eb4ce8 100644 --- a/libltdl/lt_dlloader.c +++ b/libltdl/lt_dlloader.c @@ -113,7 +113,7 @@ const lt_dlvtable * lt_dlloader_remove (const char *name) { const lt_dlvtable * vtable = lt_dlloader_find (name); - lt_dlhandle handle = 0; + lt__handle * handle = 0; int errors = 0; if (!vtable) @@ -123,7 +123,7 @@ lt_dlloader_remove (const char *name) } /* Fail if there are any open modules which use this loader. */ - while (handle = lt_dlhandle_next (handle)) + for (handle = 0; handle; handle = handle->next) { if (handle->vtable == vtable) { diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c index dd2f6f1e7..4dfc61656 100644 --- a/libltdl/ltdl.c +++ b/libltdl/ltdl.c @@ -59,8 +59,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA /* Various boolean flags can be stored in the flags field of an lt_dlhandle... */ -#define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) -#define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) +#define LT_DLGET_FLAG(handle, flag) ((((lt__handle *) handle)->flags & (flag)) == (flag)) +#define LT_DLSET_FLAG(handle, flag) (((lt__handle *)handle)->flags |= (flag)) #define LT_DLRESIDENT_FLAG (0x01 << 0) /* ...add more flags here... */ @@ -240,6 +240,7 @@ lt_dlexit (void) { /* shut down libltdl */ lt_dlloader *loader = 0; + lt__handle *handle = (lt__handle *) handles; int errors = 0; if (!initialized) @@ -256,26 +257,28 @@ lt_dlexit (void) while (handles && LT_DLIS_RESIDENT (handles)) { - handles = handles->next; + handles = ((lt__handle *) handles)->next; } /* close all modules */ - for (level = 1; handles; ++level) + for (level = 1; handle; ++level) { - lt_dlhandle cur = handles; + lt__handle *cur = (lt__handle *) handles; int saw_nonresident = 0; while (cur) { - lt_dlhandle tmp = cur; + lt__handle *tmp = cur; cur = cur->next; if (!LT_DLIS_RESIDENT (tmp)) - saw_nonresident = 1; - if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) { - if (lt_dlclose (tmp)) + saw_nonresident = 1; + if (tmp->info.ref_count <= level) { - ++errors; + if (lt_dlclose (tmp)) + { + ++errors; + } } } } @@ -307,14 +310,14 @@ lt_dlexit (void) static int tryall_dlopen (lt_dlhandle *phandle, const char *filename) { - lt_dlhandle handle = 0; + lt__handle * handle = (lt__handle *) handles; const char * saved_error = 0; int errors = 0; LT__GETERROR (saved_error); /* check whether the module was already opened */ - while (handle = lt_dlhandle_next (handle)) + for (;handle; handle = handle->next) { if ((handle->info.filename == filename) /* dlopen self: 0 == 0 */ || (handle->info.filename && filename @@ -720,7 +723,7 @@ load_deplibs (lt_dlhandle handle, char *deplibs) #endif int errors = 0; - handle->depcount = 0; + ((lt__handle *) handle)->depcount = 0; #if defined(LTDL_DLOPEN_DEPLIBS) if (!deplibs) @@ -833,22 +836,23 @@ load_deplibs (lt_dlhandle handle, char *deplibs) later on if the loaded module cannot resolve all of its symbols. */ if (depcount) { + lt__handle *cur = (lt__handle *) handle; int j = 0; - handle->deplibs = (lt_dlhandle*) MALLOC (lt_dlhandle *, depcount); - if (!handle->deplibs) + cur->deplibs = (lt_dlhandle *) MALLOC (lt__handle, depcount); + if (!cur->deplibs) goto cleanup; for (i = 0; i < depcount; ++i) { - handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); - if (handle->deplibs[j]) + cur->deplibs[j] = lt_dlopenext(names[depcount-1-i]); + if (cur->deplibs[j]) { ++j; } } - handle->depcount = j; /* Number of successfully loaded deplibs */ + cur->depcount = j; /* Number of successfully loaded deplibs */ errors = 0; } @@ -870,14 +874,15 @@ unload_deplibs (lt_dlhandle handle) { int i; int errors = 0; + lt__handle *cur = (lt__handle *) handle; - if (handle->depcount) + if (cur->depcount) { - for (i = 0; i < handle->depcount; ++i) + for (i = 0; i < cur->depcount; ++i) { - if (!LT_DLIS_RESIDENT (handle->deplibs[i])) + if (!LT_DLIS_RESIDENT (cur->deplibs[i])) { - errors += lt_dlclose (handle->deplibs[i]); + errors += lt_dlclose (cur->deplibs[i]); } } } @@ -934,11 +939,10 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) /* dlopen self? */ if (!filename) { - *phandle = (lt_dlhandle) MALLOC (struct lt_dlhandle_struct, 1); + *phandle = (lt_dlhandle) lt__zalloc (sizeof (lt__handle)); if (*phandle == 0) return 1; - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); newhandle = *phandle; /* lt_dlclose()ing yourself is very bad! Disallow it. */ @@ -1186,7 +1190,7 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) FREE (line); /* allocate the handle */ - *phandle = (lt_dlhandle) malloc (sizeof (struct lt_dlhandle_struct)); + *phandle = (lt_dlhandle) lt__zalloc (sizeof (lt__handle)); if (*phandle == 0) ++errors; @@ -1202,7 +1206,6 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) assert (*phandle); - memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); if (load_deplibs (*phandle, deplibs) == 0) { newhandle = *phandle; @@ -1237,14 +1240,13 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) else { /* not a libtool module */ - *phandle = (lt_dlhandle) MALLOC (struct lt_dlhandle_struct, 1); + *phandle = (lt_dlhandle) lt__zalloc (sizeof (lt__handle)); if (*phandle == 0) { ++errors; goto cleanup; } - memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); newhandle = *phandle; /* If the module has no directory name component, try to find it @@ -1280,13 +1282,13 @@ try_dlopen (lt_dlhandle *phandle, const char *filename) register_handle: MEMREASSIGN (*phandle, newhandle); - if ((*phandle)->info.ref_count == 0) + if (((lt__handle *) *phandle)->info.ref_count == 0) { - (*phandle)->info.ref_count = 1; - MEMREASSIGN ((*phandle)->info.name, name); + ((lt__handle *) *phandle)->info.ref_count = 1; + MEMREASSIGN (((lt__handle *) *phandle)->info.name, name); - (*phandle)->next = handles; - handles = *phandle; + ((lt__handle *) *phandle)->next = handles; + handles = *phandle; } LT__SETERRORSTR (saved_error); @@ -1640,11 +1642,11 @@ lt_dlforeachfile (const char *search_path, int lt_dlclose (lt_dlhandle handle) { - lt_dlhandle cur, last; + lt__handle *cur, *last; int errors = 0; /* check whether the handle is valid */ - last = cur = handles; + last = cur = (lt__handle *) handles; while (cur && handle != cur) { last = cur; @@ -1658,34 +1660,35 @@ lt_dlclose (lt_dlhandle handle) goto done; } - handle->info.ref_count--; + cur = (lt__handle *) handle; + cur->info.ref_count--; /* Note that even with resident modules, we must track the ref_count correctly incase the user decides to reset the residency flag later (even though the API makes no provision for that at the moment). */ - if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) + if (cur->info.ref_count <= 0 && !LT_DLIS_RESIDENT (cur)) { - lt_user_data data = handle->vtable->dlloader_data; + lt_user_data data = cur->vtable->dlloader_data; - if (handle != handles) + if (cur != handles) { - last->next = handle->next; + last->next = cur->next; } else { - handles = handle->next; + handles = cur->next; } - errors += handle->vtable->module_close (data, handle->module); - errors += unload_deplibs(handle); + errors += cur->vtable->module_close (data, cur->module); + errors += unload_deplibs (handle); /* It is up to the callers to free the data itself. */ - FREE (handle->caller_data); + FREE (cur->caller_data); - FREE (handle->info.filename); - FREE (handle->info.name); - FREE (handle); + FREE (cur->info.filename); + FREE (cur->info.name); + FREE (cur); goto done; } @@ -1701,20 +1704,23 @@ lt_dlclose (lt_dlhandle handle) } void * -lt_dlsym (lt_dlhandle handle, const char *symbol) +lt_dlsym (lt_dlhandle place, const char *symbol) { size_t lensym; char lsym[LT_SYMBOL_LENGTH]; char *sym; void *address; lt_user_data data; + lt__handle *handle; - if (!handle) + if (!place) { LT__SETERROR (INVALID_HANDLE); return 0; } + handle = (lt__handle *) place; + if (!symbol) { LT__SETERROR (SYMBOL_NOT_FOUND); @@ -1976,71 +1982,20 @@ lt_dlisresident (lt_dlhandle handle) /* --- MODULE INFORMATION --- */ -const lt_dlinfo * -lt_dlgetinfo (lt_dlhandle handle) -{ - if (!handle) - { - LT__SETERROR (INVALID_HANDLE); - return 0; - } - - return &(handle->info); -} - - -lt_dlhandle -lt_dlhandle_next (lt_dlhandle place) -{ - return place ? place->next : handles; -} - +typedef struct { + const char *id_string; + lt_dlhandle_interface *iface; +} lt__caller_id; -lt_dlhandle -lt_dlhandle_find (const char *module_name) -{ - lt_dlhandle cur = handles; - - if (cur) - { - do - { - if (cur->info.name && streq (cur->info.name, module_name)) - break; - } - while ((cur = cur->next)); - } - - return cur; -} - -int -lt_dlforeach (int (*func) (lt_dlhandle handle, void *data), void *data) +lt_dlcaller_id +lt_dlcaller_register (const char *id_string, lt_dlhandle_interface *iface) { - int errors = 0; - lt_dlhandle cur; + lt__caller_id *caller_id = lt__malloc (sizeof *caller_id); - cur = handles; - while (cur) - { - lt_dlhandle tmp = cur; + caller_id->id_string = lt__strdup (id_string); + caller_id->iface = iface; - cur = cur->next; - if ((*func) (tmp, data)) - { - ++errors; - break; - } - } - - return errors; -} - -lt_dlcaller_id -lt_dlcaller_register (void) -{ - static lt_dlcaller_id last_caller_id = 0; - return ++last_caller_id; + return (lt_dlcaller_id) caller_id; } void * @@ -2048,17 +2003,18 @@ lt_dlcaller_set_data (lt_dlcaller_id key, lt_dlhandle handle, void *data) { int n_elements = 0; void *stale = (void *) 0; + lt__handle *cur = (lt__handle *) handle; int i; - if (handle->caller_data) - while (handle->caller_data[n_elements].key) + if (cur->caller_data) + while (cur->caller_data[n_elements].key) ++n_elements; for (i = 0; i < n_elements; ++i) { - if (handle->caller_data[i].key == key) + if (cur->caller_data[i].key == key) { - stale = handle->caller_data[i].data; + stale = cur->caller_data[i].data; break; } } @@ -2068,7 +2024,7 @@ lt_dlcaller_set_data (lt_dlcaller_id key, lt_dlhandle handle, void *data) if (i == n_elements) { lt_caller_data *temp - = REALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); + = REALLOC (lt_caller_data, cur->caller_data, 2+ n_elements); if (!temp) { @@ -2076,14 +2032,14 @@ lt_dlcaller_set_data (lt_dlcaller_id key, lt_dlhandle handle, void *data) goto done; } - handle->caller_data = temp; + cur->caller_data = temp; /* We only need this if we needed to allocate a new caller_data. */ - handle->caller_data[i].key = key; - handle->caller_data[1+ i].key = 0; + cur->caller_data[i].key = key; + cur->caller_data[1+ i].key = 0; } - handle->caller_data[i].data = data; + cur->caller_data[i].data = data; done: return stale; @@ -2093,15 +2049,16 @@ void * lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle) { void *result = (void *) 0; + lt__handle *cur = (lt__handle *) handle; /* Locate the index of the element with a matching KEY. */ { int i; - for (i = 0; handle->caller_data[i].key; ++i) + for (i = 0; cur->caller_data[i].key; ++i) { - if (handle->caller_data[i].key == key) + if (cur->caller_data[i].key == key) { - result = handle->caller_data[i].data; + result = cur->caller_data[i].data; break; } } @@ -2110,6 +2067,109 @@ lt_dlcaller_get_data (lt_dlcaller_id key, lt_dlhandle handle) return result; } +const lt_dlinfo * +lt_dlgetinfo (lt_dlhandle handle) +{ + if (!handle) + { + LT__SETERROR (INVALID_HANDLE); + return 0; + } + + return &(((lt__handle *) handle)->info); +} + + +/* Nasty semantics, necessary for reasonable backwards compatibility: + Either iterate over the whole handle list starting with lt_dlhandle_next(0), + or else iterate over just the handles of modules that satisfy a given + interface by getting the first element using lt_dlhandle_first(iface). */ + +static lt__caller_id *iterator = 0; + +lt_dlhandle +lt_dlhandle_first (lt_dlcaller_id caller) +{ + iterator = caller; + + return handles; +} + + +lt_dlhandle +lt_dlhandle_next (lt_dlhandle place) +{ + lt__handle *handle = (lt__handle *) place; + + if (!handle) + { + /* old style iteration across all handles */ + iterator = 0; + handle = (lt__handle *) handles; + } + else + { + /* otherwise start at the next handle after the passed one */ + handle = handle->next; + } + + /* advance until the interface check (if we have one) succeeds */ + while (handle && iterator && iterator->iface + && (iterator->iface (handle, iterator->id_string) != 0)) + { + handle = handle->next; + } + + if (!handle) + { + /* clear the iterator after the last handle */ + iterator = 0; + } + + return (lt_dlhandle) handle; +} + + +lt_dlhandle +lt_dlhandle_find (const char *module_name) +{ + lt__handle *cur = (lt__handle *) handles; + + if (cur) + { + do + { + if (cur->info.name && streq (cur->info.name, module_name)) + break; + } + while ((cur = cur->next)); + } + + return cur; +} + +int +lt_dlforeach (int (*func) (lt_dlhandle handle, void *data), void *data) +{ + int errors = 0; + lt__handle *cur; + + cur = (lt__handle *) handles; + while (cur) + { + lt__handle *tmp = cur; + + cur = cur->next; + if ((*func) (tmp, data)) + { + ++errors; + break; + } + } + + return errors; +} + /* These symbols are part of the published interface to libltdl, diff --git a/libltdl/ltdl.h b/libltdl/ltdl.h index 34ac39cef..fd56505be 100644 --- a/libltdl/ltdl.h +++ b/libltdl/ltdl.h @@ -45,7 +45,7 @@ LT_BEGIN_C_DECLS /* --- DYNAMIC MODULE LOADING API --- */ -typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ +typedef void * lt_dlhandle; /* A loaded module. */ /* Initialisation and finalisation functions for libltdl. */ LT_SCOPE int lt_dlinit (void); @@ -110,6 +110,17 @@ LT_SCOPE int lt_dlpreload_open (const char *originator, /* --- MODULE INFORMATION --- */ +/* Associating user data with loaded modules. */ +typedef void * lt_dlcaller_id; +typedef int lt_dlhandle_interface (lt_dlhandle handle, const char *id_string); + +LT_SCOPE lt_dlcaller_id lt_dlcaller_register (const char *id_string, + lt_dlhandle_interface *iface); +LT_SCOPE void * lt_dlcaller_set_data (lt_dlcaller_id key, + lt_dlhandle handle, void *data); +LT_SCOPE void * lt_dlcaller_get_data (lt_dlcaller_id key, + lt_dlhandle handle); + /* Read only information pertaining to a loaded module. */ typedef struct { char * filename; /* file name */ @@ -119,21 +130,13 @@ typedef struct { } lt_dlinfo; LT_SCOPE const lt_dlinfo *lt_dlgetinfo (lt_dlhandle handle); +LT_SCOPE lt_dlhandle lt_dlhandle_first (lt_dlcaller_id key); LT_SCOPE lt_dlhandle lt_dlhandle_next (lt_dlhandle place); LT_SCOPE lt_dlhandle lt_dlhandle_find (const char *module_name); LT_SCOPE int lt_dlforeach ( int (*func) (lt_dlhandle handle, void *data), void *data); -/* Associating user data with loaded modules. */ -typedef unsigned lt_dlcaller_id; - -LT_SCOPE lt_dlcaller_id lt_dlcaller_register (void); -LT_SCOPE void * lt_dlcaller_set_data (lt_dlcaller_id key, - lt_dlhandle handle, void *data); -LT_SCOPE void * lt_dlcaller_get_data (lt_dlcaller_id key, - lt_dlhandle handle); - /* --- BINARY COMPATIBILITY WITH OLD LIBLTDL --- */ -- 2.47.2