GNU Info

Info Node: (libtool.info)Module loaders for libltdl

(libtool.info)Module loaders for libltdl


Next: Distributing libltdl Prev: User defined module data Up: Using libltdl
Enter node , (file) or (file)node

How to create and register new module loaders
=============================================

   Sometimes libltdl's many ways of gaining access to modules are not
sufficient for the purposes of a project.  You can write your own
loader, and register it with libltdl so that `lt_dlopen' will be able
to use it.

   Writing a loader involves writing at least three functions which can
be called  by `lt_dlopen', `lt_dlsym' and `lt_dlclose'.  Optionally,
you can provide a finalisation function to perform any cleanup
operations when `lt_dlexit' executes, and a symbol prefix string which
will be prepended to any symbols passed to `lt_dlsym'.  These functions
must match the function pointer types below, after which they can be
allocated to an instance of `lt_user_dlloader' and registered.

   Registering the loader requires that you choose a name for it, so
that it can be recognised by `lt_dlloader_find' and removed with
`lt_dlloader_remove'.  The name you choose must be unique, and not
already in use by libltdl's builtin loaders:

"dlopen"
     The system dynamic library loader, if one exists.

"dld"
     The GNU dld loader, if `libdld' was installed when libltdl was
     built.

"dlpreload"
     The loader for `lt_dlopen'ing of preloaded static modules.

   The prefix "dl" is reserved for loaders supplied with future
versions of libltdl, so you should not use that for your own loader
names.

The following types are defined in `ltdl.h':

 - Type: lt_module
     `lt_module' is a dlloader dependent module.  The dynamic module
     loader extensions communicate using these low level types.

 - Type: lt_dlloader
     `lt_dlloader' is a handle for module loader types.

 - Type: lt_dlloader_data
     `lt_dlloader_data' is used for specifying loader instance data.

 - Type: struct lt_user_dlloader {const char *SYM_PREFIX;
          lt_module_open *MODULE_OPEN;lt_module_close *MODULE_CLOSE;
          lt_find_sym *FIND_SYM; lt_dlloader_exit *DLLOADER_EXIT;
          lt_dlloader_data DLLOADER_DATA; }
     If you want to define a new way to open dynamic modules, and have
     the `lt_dlopen' API use it, you need to instantiate one of these
     structures and pass it to `lt_dlloader_add'.  You can pass whatever
     you like in the DLLOADER_DATA field, and it will be passed back as
     the value of the first parameter to each of the functions
     specified in the function pointer fields.

 - Type: lt_module lt_module_open (lt_user_data LOADER_DATA,
          const char *FILENAME)
     The type of the loader function for an `lt_dlloader' module
     loader.  The value set in the dlloader_data field of the `struct
     lt_user_dlloader' structure will be passed into this function in
     the LOADER_DATA parameter.  Implementation of such a function
     should attempt to load the named module, and return an `lt_module'
     suitable for passing in to the associated `lt_module_close' and
     `lt_sym_find' function pointers.  If the function fails it should
     return `NULL', and set the error message with `lt_dlseterror'.

 - Type: int lt_module_close (lt_dlloader_data LOADER_DATA,
          lt_module MODULE)
     The type of the unloader function for a user defined module loader.
     Implementatation of such a function should attempt to release any
     resources tied up by the MODULE module, and then unload it from
     memory.  If the function fails for some reason, set the error
     message with `lt_dlseterror' and return non-zero.

 - Type: lt_ptr lt_find_sym (lt_user_data LOADER_DATA,
          lt_module MODULE, const char *SYMBOL)
     The type of the symbol lookup function for a user defined module
     loader.  Implementation of such a function should return the
     address of the named SYMBOL in the module MODULE, or else set the
     error message with `lt_dlseterror' and return `NULL' if lookup
     fails.

 - Type: int lt_dlloader_exit (lt_user_data LOADER_DATA)
     The type of the finalisation function for a user defined module
     loader.  Implementation of such a function should free any
     resources associated with the loader, including any user specified
     data in the `dlloader_data' field of the `lt_user_dlloader'.  If
     non-`NULL', the function will be called by `lt_dlexit', and
     `lt_dlloader_remove'.

   For example:

     int
     register_myloader (void)
     {
       lt_user_dlloader dlloader;
     
       /* User modules are responsible for their own initialisation. */
       if (myloader_init () != 0)
         return MYLOADER_INIT_ERROR;
     
       dlloader.sym_prefix    = NULL;
       dlloader.module_open   = myloader_open;
       dlloader.module_close  = myloader_close;
       dlloader.find_sym      = myloader_find_sym.
       dlloader.dlloader_exit = myloader_exit;
       dlloader.dlloader_data = (lt_user_data)myloader_function;
     
       /* Add my loader as the default module loader. */
       if (lt_dlloader_add (lt_dlloader_next (NULL), &dlloader, "myloader") != 0)
         return ERROR;
     
       return OK;
     }

   Note that if there is any initialisation required for the loader, it
must be performed manually before the loader is registered - libltdl
doesn't handle user loader initialisation.

   Finalisation _is_ handled by libltdl however, and it is important to
ensure the `dlloader_exit' callback releases any resources claimed
during the initialisation phase.

libltdl provides the following functions for writing your own module
loaders:

 - Function: int lt_dlloader_add (lt_dlloader *PLACE,
          lt_user_dlloader *DLLOADER, const char *LOADER_NAME)
     Add a new module loader to the list of all loaders, either as the
     last loader (if PLACE is `NULL'), else immediately before the
     loader passed as PLACE.  LOADER_NAME will be returned by
     `lt_dlloader_name' if it is subsequently passed a newly registered
     loader.  These LOADER_NAMEs must be unique, or
     `lt_dlloader_remove' and `lt_dlloader_find' cannot work. Returns 0
     for success.

          {
            /* Make myloader be the last one. */
            if (lt_dlloader_add (NULL, myloader) != 0)
              perror (lt_dlerror ());
          }

 - Function: int lt_dlloader_remove (const char *LOADER_NAME)
     Remove the loader identified by the unique name, LOADER_NAME.
     Before this can succeed, all modules opened by the named loader
     must have been closed.  Returns 0 for success, otherwise an error
     message can be obtained from `lt_dlerror'.

          {
            /* Remove myloader. */
            if (lt_dlloader_remove ("myloader") != 0)
              perror (lt_dlerror ());
          }

 - Function: lt_dlloader * lt_dlloader_next (lt_dlloader *PLACE)
     Iterate over the module loaders, returning the first loader if
     PLACE is `NULL', and the next one on subsequent calls. The handle
     is for use with `lt_dlloader_add'.

          {
            /* Make myloader be the first one. */
            if (lt_dlloader_add (lt_dlloader_next (NULL), myloader) != 0)
              return ERROR;
          }

 - Function: lt_dlloader * lt_dlloader_find (const char *LOADER_NAME)
     Return the first loader with a matching LOADER_NAME identifier, or
     else `NULL', if the identifier is not found.

     The identifiers which may be used by libltdl itself, if the host
     architecture supports them are "dlopen"(1), "dld" and "dlpreload".

          {
            /* Add a user loader as the next module loader to be tried if
               the standard dlopen loader were to fail when lt_dlopening. */
            if (lt_dlloader_add (lt_dlloader_find ("dlopen"), myloader) != 0)
              return ERROR;
          }

 - Function: const char * lt_dlloader_name (lt_dlloader *PLACE)
     Return the identifying name of PLACE, as obtained from
     `lt_dlloader_next' or `lt_dlloader_find'.  If this function fails,
     it will return `NULL' and set an error for retrieval with
     `lt_dlerror'.

 - Function: lt_user_data * lt_dlloader_data (lt_dlloader *PLACE)
     Return the address of the `dlloader_data' of PLACE, as obtained
     from `lt_dlloader_next' or `lt_dlloader_find'.  If this function
     fails, it will return `NULL' and set an error for retrieval with
     `lt_dlerror'.

Error handling within user module loaders
-----------------------------------------

 - Function: int lt_dladderror (const char *DIAGNOSTIC)
     This function allows you to integrate your own error messages into
     `lt_dlerror'.  Pass in a suitable diagnostic message for return by
     `lt_dlerror', and an error identifier for use with `lt_dlseterror'
     is returned.

     If the allocation of an identifier fails, this function returns -1.

          int myerror = lt_dladderror ("Doh!");
          if (myerror < 0)
            perror (lt_dlerror ());

 - Function: int lt_dlseterror (int ERRORCODE)
     When writing your own module loaders, you should use this function
     to raise errors so that they are propogated through the
     `lt_dlerror' interface. All of the standard errors used by libltdl
     are declared in `ltdl.h', or you can add more of your own with
     `lt_dladderror'.  This function returns 0 on success.

          if (lt_dlseterror (LTDL_ERROR_NO_MEMORY) != 0)
            perror (lt_dlerror ());

   ---------- Footnotes ----------

   (1) This is used for the host dependent module loading API -
`shl_load' and `LoadLibrary' for example


automatically generated by info2www version 1.2.2.9