Go to the first, previous, next, last section, table of contents.
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:
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':
lt_module
is a dlloader dependent module.
The dynamic module loader extensions communicate using these low
level types.
lt_dlloader
is a handle for module loader types.
lt_dlloader_data
is used for specifying loader instance data.
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.
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
.
lt_dlseterror
and return non-zero.
lt_dlseterror
and return NULL
if lookup fails.
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:
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 ()); }
lt_dlerror
.
{ /* Remove myloader. */ if (lt_dlloader_remove ("myloader") != 0) perror (lt_dlerror ()); }
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; }
NULL
, if the identifier is not found.
The identifiers which may be used by libltdl itself, if the host architecture supports them are dlopen(9), 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; }
lt_dlloader_next
or lt_dlloader_find
. If this function fails,
it will return NULL
and set an error for retrieval with
lt_dlerror
.
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
.
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 ());
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 ());
Go to the first, previous, next, last section, table of contents.