11.1 How to use libltdl in your programs

The libltdl API is similar to the POSIX dlopen interface, which is very simple but powerful.

To use libltdl in your program you have to include the header file ltdl.h:

#include <ltdl.h>

The early releases of libltdl used some symbols that violated the POSIX namespace conventions. These symbols are now deprecated, and have been replaced by those described here. If you have code that relies on the old deprecated symbol names, defining ‘LT_NON_POSIX_NAMESPACE’ before you include ltdl.h provides conversion macros. Whichever set of symbols you use, the new API is not binary compatible with the last, so you will need to recompile your application to use this version of libltdl.

Note that libltdl is not well tested in a multithreaded environment, though the intention is that it should work (see Using libltdl in a multi threaded environment). If there are any issues, working around them is left as an exercise for the reader; contributions are certainly welcome.

The following macros are defined by including ltdl.h:

Macro: LT_PATHSEP_CHAR

LT_PATHSEP_CHAR is the system-dependent path separator, that is, ‘;’ on Windows and ‘:’ everywhere else.

Macro: LT_DIRSEP_CHAR

If LT_DIRSEP_CHAR is defined, it can be used as directory separator in addition to ‘/’. On Windows, this contains ‘\’.

The following types are defined in ltdl.h:

Type: lt_dlhandle

lt_dlhandle is a module “handle”. Every lt_dlopened module has a handle associated with it.

Type: lt_dladvise

lt_dladvise is used to control optional module loading modes. If it is not used, the default mode of the underlying system module loader is used.

Type: lt_dlsymlist

lt_dlsymlist is a symbol list for dlpreopened modules (see Dlpreopening).

libltdl provides the following functions:

Function: int lt_dlinit (void)

Initialize libltdl. This function must be called before using libltdl and may be called several times. Return 0 on success, otherwise the number of errors.

Function: int lt_dlexit (void)

Shut down libltdl and close all modules. This function will only then shut down libltdl when it was called as many times as lt_dlinit has been successfully called. Return 0 on success, otherwise the number of errors.

Function: lt_dlhandle lt_dlopen (const char *filename)

Open the module with the file name filename and return a handle for it. lt_dlopen is able to open libtool dynamic modules, preloaded static modules, the program itself and native dynamic modules11.

Unresolved symbols in the module are resolved using its dependency libraries and, on some platforms, previously dlopened modules. If the executable using this module was linked with the -export-dynamic flag, then the global symbols in the executable will also be used to resolve references in the module.

If filename is NULL and the program was linked with -export-dynamic or -dlopen self, lt_dlopen will return a handle for the program itself, which can be used to access its symbols.

If libltdl cannot find the library and the file name filename does not have a directory component it will additionally look in the following search paths for the module (in the following order):

  1. user-defined search path: This search path can be changed by the program using the functions lt_dlsetsearchpath, lt_dladdsearchdir and lt_dlinsertsearchdir.
  2. libltdl’s search path: This search path is the value of the environment variable LTDL_LIBRARY_PATH.
  3. system library search path: The system dependent library search path (e.g. on GNU/Linux it is LD_LIBRARY_PATH).

Each search path must be a list of absolute directories separated by LT_PATHSEP_CHAR, for example, "/usr/lib/mypkg:/lib/foo". The directory names may not contain the path separator.

If the same module is loaded several times, the same handle is returned. If lt_dlopen fails for any reason, it returns NULL.

Function: lt_dlhandle lt_dlopenext (const char *filename)

The same as lt_dlopen, except that it tries to append different file name extensions to the file name. If the file with the file name filename cannot be found libltdl tries to append the following extensions:

  1. the libtool archive extension .la
  2. the extension used for native dynamically loadable modules on the host platform, e.g., .so, .sl, etc.

This lookup strategy was designed to allow programs that don’t have knowledge about native dynamic libraries naming conventions to be able to dlopen such libraries as well as libtool modules transparently.

Function: lt_dlhandle lt_dlopenadvise (const char *filename, lt_dladvise advise)

The same as lt_dlopen, except that it also requires an additional argument that may contain additional hints to the underlying system module loader. The advise parameter is opaque and can only be accessed with the functions documented below.

Note that this function does not change the content of advise, so unlike the other calls in this API takes a direct lt_dladvise type, and not a pointer to the same.

Function: int lt_dladvise_init (lt_dladvise *advise)

The advise parameter can be used to pass hints to the module loader when using lt_dlopenadvise to perform the loading. The advise parameter needs to be initialised by this function before it can be used. Any memory used by advise needs to be recycled with lt_dladvise_destroy when it is no longer needed.

On failure, lt_dladvise_init returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_destroy (lt_dladvise *advise)

Recycle the memory used by advise. For an example, see the documentation for lt_dladvise_ext.

On failure, lt_dladvise_destroy returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_ext (lt_dladvise *advise)

Set the ext hint on advise. Passing an advise parameter to lt_dlopenadvise with this hint set causes it to try to append different file name extensions like lt_dlopenext.

The following example is equivalent to calling lt_dlopenext (filename):

lt_dlhandle
my_dlopenext (const char *filename)
{
  lt_dlhandle handle = 0;
  lt_dladvise advise;

  if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
    handle = lt_dlopenadvise (filename, advise);

  lt_dladvise_destroy (&advise);

  return handle;
}

On failure, lt_dladvise_ext returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_global (lt_dladvise *advise)

Set the symglobal hint on advise. Passing an advise parameter to lt_dlopenadvise with this hint set causes it to try to make the loaded module’s symbols globally available for resolving unresolved symbols in subsequently loaded modules.

If neither the symglobal nor the symlocal hints are set, or if a module is loaded without using the lt_dlopenadvise call in any case, then the visibility of the module’s symbols will be as per the default for the underlying module loader and OS. Even if a suitable hint is passed, not all loaders are able to act upon it in which case lt_dlgetinfo will reveal whether the hint was actually followed.

On failure, lt_dladvise_global returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_local (lt_dladvise *advise)

Set the symlocal hint on advise. Passing an advise parameter to lt_dlopenadvise with this hint set causes it to try to keep the loaded module’s symbols hidden so that they are not visible to subsequently loaded modules.

If neither the symglobal nor the symlocal hints are set, or if a module is loaded without using the lt_dlopenadvise call in any case, then the visibility of the module’s symbols will be as per the default for the underlying module loader and OS. Even if a suitable hint is passed, not all loaders are able to act upon it in which case lt_dlgetinfo will reveal whether the hint was actually followed.

On failure, lt_dladvise_local returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_resident (lt_dladvise *advise)

Set the resident hint on advise. Passing an advise parameter to lt_dlopenadvise with this hint set causes it to try to make the loaded module resident in memory, so that it cannot be unloaded with a later call to lt_dlclose.

On failure, lt_dladvise_resident returns non-zero and sets an error message that can be retrieved with lt_dlerror.

Function: int lt_dladvise_preload (lt_dladvise *advise)

Set the preload hint on advise. Passing an advise parameter to lt_dlopenadvise with this hint set causes it to load only preloaded modules, so that if a suitable preloaded module is not found, lt_dlopenadvise will return NULL.

Function: int lt_dlclose (lt_dlhandle handle)

Decrement the reference count on the module handle. If it drops to zero and no other module depends on this module, then the module is unloaded. Return 0 on success.

Function: void * lt_dlsym (lt_dlhandle handle, const char *name)

Return the address in the module handle, where the symbol given by the null-terminated string name is loaded. If the symbol cannot be found, NULL is returned.

Function: const char * lt_dlerror (void)

Return a human readable string describing the most recent error that occurred from any of libltdl’s functions. Return NULL if no errors have occurred since initialization or since it was last called.

Function: int lt_dladdsearchdir (const char *search_dir)

Append the search directory search_dir to the current user-defined library search path. Return 0 on success.

Function: int lt_dlinsertsearchdir (const char *before, const char *search_dir)

Insert the search directory search_dir into the user-defined library search path, immediately before the element starting at address before. If before is ‘NULL’, then search_dir is appending as if lt_dladdsearchdir had been called. Return 0 on success.

Function: int lt_dlsetsearchpath (const char *search_path)

Replace the current user-defined library search path with search_path, which must be a list of absolute directories separated by LT_PATHSEP_CHAR. Return 0 on success.

Function: const char * lt_dlgetsearchpath (void)

Return the current user-defined library search path.

Function: int lt_dlforeachfile (const char *search_path, int (*func) (const char *filename, void * data), void * data)

In some applications you may not want to load individual modules with known names, but rather find all of the modules in a set of directories and load them all during initialisation. With this function you can have libltdl scan the LT_PATHSEP_CHAR-delimited directory list in search_path for candidates, and pass them, along with data to your own callback function, func. If search_path is ‘NULL’, then search all of the standard locations that lt_dlopen would examine. This function will continue to make calls to func for each file that it discovers in search_path until one of these calls returns non-zero, or until the files are exhausted. ‘lt_dlforeachfile’ returns the value returned by the last call made to func.

For example you could define func to build an ordered argv-like vector of files using data to hold the address of the start of the vector.

Function: int lt_dlmakeresident (lt_dlhandle handle)

Mark a module so that it cannot be ‘lt_dlclose’d. This can be useful if a module implements some core functionality in your project that would cause your code to crash if removed. Return 0 on success.

If you use ‘lt_dlopen (NULL)’ to get a handle for the running binary, that handle will always be marked as resident, and consequently cannot be successfully ‘lt_dlclose’d.

Function: int lt_dlisresident (lt_dlhandle handle)

Check whether a particular module has been marked as resident, returning 1 if it has or 0 otherwise. If there is an error while executing this function, return -1 and set an error message for retrieval with lt_dlerror.


Footnotes

(11)

Some platforms, notably Mac OS X, differentiate between a runtime library that cannot be opened by lt_dlopen and a dynamic module that can. For maximum portability you should try to ensure that you only pass lt_dlopen objects that have been compiled with libtool’s -module flag.