libtool: User defined module data
1
1 11.4 Data associated with loaded modules
1 ========================================
1
1 Some of the internal information about each loaded module that is
1 maintained by libltdl is available to the user, in the form of this
1 structure:
1
1 -- Type: struct lt_dlinfo { char *FILENAME; char *NAME; int REF_COUNT; int IS_RESIDENT;
1 int IS_SYMGLOBAL; int IS_SYMLOCAL;}
1 'lt_dlinfo' is used to store information about a module. The
1 FILENAME attribute is a null-terminated character string of the
1 real module file name. If the module is a libtool module then NAME
1 is its module name (e.g. '"libfoo"' for '"dir/libfoo.la"'),
1 otherwise it is set to 'NULL'. The REF_COUNT attribute is a
1 reference counter that describes how often the same module is
1 currently loaded. The remaining fields can be compared to any
1 hints that were passed to 'lt_dlopenadvise' to determine whether
1 the underlying loader was able to follow them.
1
1 The following function will return a pointer to libltdl's internal
1 copy of this structure for the given HANDLE:
1
1 -- Function: const lt_dlinfo * lt_dlgetinfo (lt_dlhandle HANDLE)
1 Return a pointer to a struct that contains some information about
1 the module HANDLE. The contents of the struct must not be
1 modified. Return 'NULL' on failure.
1
1 Furthermore, to save you from having to keep a list of the handles of
1 all the modules you have loaded, these functions allow you to iterate
1 over libltdl's list of loaded modules:
1
1 -- Type: lt_dlinterface_id
1 The opaque type used to hold the module interface details for each
1 registered libltdl client.
1
1 -- Type: int lt_dlhandle_interface (lt_dlhandle HANDLE,
1 const char *ID_STRING)
1 Functions of this type are called to check that a handle conforms
1 to a library's expected module interface when iterating over the
1 global handle list. You should be careful to write a callback
1 function of this type that can correctly identify modules that
1 belong to this client, both to prevent other clients from
1 accidentally finding your loaded modules with the iterator
1 functions below, and vice versa. The best way to do this is to
1 check that module HANDLE conforms to the interface specification of
1 your loader using 'lt_dlsym'.
1
1 The callback may be given *every* module loaded by all the libltdl
1 module clients in the current address space, including any modules
1 loaded by other libraries such as libltdl itself, and should return
1 non-zero if that module does not fulfill the interface requirements
1 of your loader.
1
1 int
1 my_interface_cb (lt_dlhandle handle, const char *id_string)
1 {
1 char *(*module_id) (void) = NULL;
1
1 /* A valid my_module must provide all of these symbols. */
1 if (!((module_id = (char*(*)(void)) lt_dlsym ("module_version"))
1 && lt_dlsym ("my_module_entrypoint")))
1 return 1;
1
1 if (strcmp (id_string, module_id()) != 0)
1 return 1;
1
1 return 0;
1 }
1
1 -- Function: lt_dlinterface_id lt_dlinterface_register
1 (const char *ID_STRING, lt_dlhandle_interface *IFACE)
1 Use this function to register your interface validator with
1 libltdl, and in return obtain a unique key to store and retrieve
1 per-module data. You supply an ID_STRING and IFACE so that the
1 resulting 'lt_dlinterface_id' can be used to filter the module
1 handles returned by the iteration functions below. If IFACE is
1 'NULL', all modules will be matched.
1
1 -- Function: void lt_dlinterface_free (lt_dlinterface_id IFACE)
1 Release the data associated with IFACE.
1
1 -- Function: int lt_dlhandle_map (lt_dlinterface_id IFACE,
1 int (*FUNC) (lt_dlhandle HANDLE, void * DATA), void * DATA)
1 For each module that matches IFACE, call the function FUNC. When
1 writing the FUNC callback function, the argument HANDLE is the
1 handle of a loaded module, and DATA is the last argument passed to
1 'lt_dlhandle_map'. As soon as FUNC returns a non-zero value for
1 one of the handles, 'lt_dlhandle_map' will stop calling FUNC and
1 immediately return that non-zero value. Otherwise 0 is eventually
1 returned when FUNC has been successfully called for all matching
1 modules.
1
1 -- Function: lt_dlhandle lt_dlhandle_iterate
1 (lt_dlinterface_id IFACE, lt_dlhandle PLACE)
1 Iterate over the module handles loaded by IFACE, returning the
1 first matching handle in the list if PLACE is 'NULL', and the next
1 one on subsequent calls. If PLACE is the last element in the list
1 of eligible modules, this function returns 'NULL'.
1
1 lt_dlhandle handle = 0;
1 lt_dlinterface_id iface = my_interface_id;
1
1 while ((handle = lt_dlhandle_iterate (iface, handle)))
1 {
1 ...
1 }
1
1 -- Function: lt_dlhandle lt_dlhandle_fetch (lt_dlinterface_id IFACE,
1 const char *MODULE_NAME)
1 Search through the module handles loaded by IFACE for a module
1 named MODULE_NAME, returning its handle if found or else 'NULL' if
1 no such named module has been loaded by IFACE.
1
1 However, you might still need to maintain your own list of loaded
1 module handles (in parallel with the list maintained inside libltdl) if
1 there were any other data that your application wanted to associate with
1 each open module. Instead, you can use the following API calls to do
1 that for you. You must first obtain a unique interface id from libltdl
1 as described above, and subsequently always use it to retrieve the data
1 you stored earlier. This allows different libraries to each store their
1 own data against loaded modules, without interfering with one another.
1
1 -- Function: void * lt_dlcaller_set_data (lt_dlinterface_id KEY,
1 lt_dlhandle HANDLE, void * DATA)
1 Set DATA as the set of data uniquely associated with KEY and HANDLE
1 for later retrieval. This function returns the DATA previously
1 associated with KEY and HANDLE if any. A result of 0, may indicate
1 that a diagnostic for the last error (if any) is available from
1 'lt_dlerror()'.
1
1 For example, to correctly remove some associated data:
1
1 void *stale = lt_dlcaller_set_data (key, handle, 0);
1 if (stale != NULL)
1 {
1 free (stale);
1 }
1 else
1 {
1 char *error_msg = lt_dlerror ();
1
1 if (error_msg != NULL)
1 {
1 my_error_handler (error_msg);
1 return STATUS_FAILED;
1 }
1 }
1
1 -- Function: void * lt_dlcaller_get_data (lt_dlinterface_id KEY,
1 lt_dlhandle HANDLE)
1 Return the address of the data associated with KEY and HANDLE, or
1 else 'NULL' if there is none.
1
1 Old versions of libltdl also provided a simpler, but similar, API
1 based around 'lt_dlcaller_id'. Unfortunately, it had no provision for
1 detecting whether a module belonged to a particular interface as libltdl
1 didn't support multiple loaders in the same address space at that time.
1 Those APIs are no longer supported as there would be no way to stop
1 clients of the old APIs from seeing (and accidentally altering) modules
1 loaded by other libraries.
1