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:
LT_PATHSEP_CHAR
is the system-dependent path separator,
that is, ‘;’ on Windows and ‘:’ everywhere else.
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:
lt_dlhandle
is a module “handle”.
Every lt_dlopened module has a handle associated with it.
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.
lt_dlsymlist
is a symbol list for dlpreopened modules
(see Dlpreopening).
libltdl provides the following functions:
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.
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.
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):
lt_dlsetsearchpath
, lt_dladdsearchdir
and
lt_dlinsertsearchdir
.
LTDL_LIBRARY_PATH
.
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
.
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:
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.
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.
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
.
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
.
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
.
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
.
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
.
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
.
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
.
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.
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.
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.
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.
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.
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.
const char *
lt_dlgetsearchpath (void)
¶Return the current user-defined library search path.
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.
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.
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
.
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.