manpagez: man pages & more
info libtool
Home | html | info | man

File: libtool.info,  Node: User defined module data,  Next: Module loaders for libltdl,  Prev: Thread Safety in libltdl,  Up: Using libltdl

11.4 Data associated with loaded modules
========================================

Some of the internal information about each loaded module that is
maintained by libltdl is available to the user, in the form of this
structure:

 -- Type: struct lt_dlinfo { char *filename; char *name; int ref_count;
          int is_resident; int is_symglobal; int is_symlocal;}
     ‘lt_dlinfo’ is used to store information about a module.  The
     ‘filename’ attribute is a null-terminated character string of the
     real module file name.  If the module is a libtool module then
     ‘name’ is its module name (e.g. ‘"libfoo"’ for ‘"dir/libfoo.la"’),
     otherwise it is set to ‘NULL’.  The ‘ref_count’ attribute is a
     reference counter that describes how often the same module is
     currently loaded.  The remaining fields can be compared to any
     hints that were passed to ‘lt_dlopenadvise’ to determine whether
     the underlying loader was able to follow them.

   The following function will return a pointer to libltdl's internal
copy of this structure for the given HANDLE:

 -- Function: const lt_dlinfo * lt_dlgetinfo (lt_dlhandle HANDLE)
     Return a pointer to a struct that contains some information about
     the module HANDLE.  The contents of the struct must not be
     modified.  Return ‘NULL’ on failure.

   Furthermore, to save you from having to keep a list of the handles of
all the modules you have loaded, these functions allow you to iterate
over libltdl's list of loaded modules:

 -- Type: lt_dlinterface_id
     The opaque type used to hold the module interface details for each
     registered libltdl client.

 -- Type: int lt_dlhandle_interface (lt_dlhandle HANDLE,
          const char *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.  You should be careful to write a callback
     function of this type that can correctly identify modules that
     belong to this client, both to prevent other clients from
     accidentally finding your loaded modules with the iterator
     functions below, and vice versa.  The best way to do this is to
     check that module HANDLE conforms to the interface specification of
     your loader using ‘lt_dlsym’.

     The callback may be given *every* module loaded by all the libltdl
     module clients in the current address space, including any modules
     loaded by other libraries such as libltdl itself, and should return
     non-zero if that module does not fulfill the interface requirements
     of your loader.

          int
          my_interface_cb (lt_dlhandle handle, const char *id_string)
          {
            char *(*module_id) (void) = NULL;

            /* A valid my_module must provide all of these symbols.  */
            if (!((module_id = (char*(*)(void)) lt_dlsym ("module_version"))
                  && lt_dlsym ("my_module_entrypoint")))
                return 1;

            if (strcmp (id_string, module_id()) != 0)
                return 1;

            return 0;
          }

 -- Function: lt_dlinterface_id lt_dlinterface_register
          (const char *ID_STRING, lt_dlhandle_interface *IFACE)
     Use this function to register your interface validator with
     libltdl, and in return obtain a unique key to store and retrieve
     per-module data.  You supply an ID_STRING and IFACE so that the
     resulting ‘lt_dlinterface_id’ can be used to filter the module
     handles returned by the iteration functions below.  If IFACE is
     ‘NULL’, all modules will be matched.

 -- Function: void lt_dlinterface_free (lt_dlinterface_id IFACE)
     Release the data associated with IFACE.

 -- Function: int lt_dlhandle_map (lt_dlinterface_id IFACE,
          int (*FUNC) (lt_dlhandle HANDLE, void * DATA), void * DATA)
     For each module that matches IFACE, call the function FUNC.  When
     writing the FUNC callback function, the argument HANDLE is the
     handle of a loaded module, and DATA is the last argument passed to
     ‘lt_dlhandle_map’.  As soon as FUNC returns a non-zero value for
     one of the handles, ‘lt_dlhandle_map’ will stop calling FUNC and
     immediately return that non-zero value.  Otherwise 0 is eventually
     returned when FUNC has been successfully called for all matching
     modules.

 -- Function: lt_dlhandle lt_dlhandle_iterate (lt_dlinterface_id IFACE,
          lt_dlhandle PLACE)
     Iterate over the module handles loaded by IFACE, returning the
     first matching handle in the list if PLACE is ‘NULL’, and the next
     one on subsequent calls.  If PLACE is the last element in the list
     of eligible modules, this function returns ‘NULL’.

          lt_dlhandle handle = 0;
          lt_dlinterface_id iface = my_interface_id;

          while ((handle = lt_dlhandle_iterate (iface, handle)))
            {
              ...
            }

 -- Function: lt_dlhandle lt_dlhandle_fetch (lt_dlinterface_id IFACE,
          const char *MODULE_NAME)
     Search through the module handles loaded by IFACE for a module
     named MODULE_NAME, returning its handle if found or else ‘NULL’ if
     no such named module has been loaded by IFACE.

   However, you might still need to maintain your own list of loaded
module handles (in parallel with the list maintained inside libltdl) if
there were any other data that your application wanted to associate with
each open module.  Instead, you can use the following API calls to do
that for you.  You must first obtain a unique interface id from libltdl
as described above, and subsequently always use it to retrieve the data
you stored earlier.  This allows different libraries to each store their
own data against loaded modules, without interfering with one another.

 -- Function: void * lt_dlcaller_set_data (lt_dlinterface_id KEY,
          lt_dlhandle HANDLE, void * DATA)
     Set DATA as the set of data uniquely associated with KEY and HANDLE
     for later retrieval.  This function returns the DATA previously
     associated with KEY and HANDLE if any.  A result of 0, may indicate
     that a diagnostic for the last error (if any) is available from
     ‘lt_dlerror()’.

     For example, to correctly remove some associated data:

          void *stale = lt_dlcaller_set_data (key, handle, 0);
          if (stale != NULL)
            {
              free (stale);
            }
          else
            {
              char *error_msg = lt_dlerror ();

              if (error_msg != NULL)
                {
                  my_error_handler (error_msg);
                  return STATUS_FAILED;
                }
            }

 -- Function: void * lt_dlcaller_get_data (lt_dlinterface_id KEY,
          lt_dlhandle HANDLE)
     Return the address of the data associated with KEY and HANDLE, or
     else ‘NULL’ if there is none.

   Old versions of libltdl also provided a simpler, but similar, API
based around ‘lt_dlcaller_id’.  Unfortunately, it had no provision for
detecting whether a module belonged to a particular interface as libltdl
didn't support multiple loaders in the same address space at that time.
Those APIs are no longer supported as there would be no way to stop
clients of the old APIs from seeing (and accidentally altering) modules
loaded by other libraries.

© manpagez.com 2000-2025
Individual documents may contain additional copyright information.