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