|
|
[Contents]
[Previous] [Next][Last]
Chapter 19
Dynamic Library Linking
This section describes NSPR's programming interface to load, unload and
resolve symbols in dynamic libraries. It also provides a method by which
one can condition symbols of statically linked code so that to other clients
it appears as though they are dynamically loaded.
Types
Functions
Platform Notes
Types
PRLibrary
A PRLibrary is an opaque structure. A reference to such
a structure may be returned by some of the functions in the runtime and
serve to identify a particular instance of a library.
typedef struct PRLibrary PRLibrary;
PRStaticLinkTable
A static link table entry may be created by a client of the runtime so
that other clients can access static or dynamic libraries transparently.
The basic function on a dynamic library is to acquire a pointer to a function
that the library exports. If, during initialization, such entries are manually
created, then future attempts to link to the symbols can be treated in
a consistent fashion.
typedef struct PRStaticLinkTable {
const char *name;
void (*fp)();
} PRStaticLinkTable;
Functions
PR_SetLibraryPath
For convenience, a default library pathname may be registered with the
runtime. This allows an environment to express policy decisions globally
and lazily rather than hardcoding and distributing the decisions throughout
the code.
PRStatus PR_SetLibraryPath(const
char *path);
Parameters
| path |
A pointer to a character array that contains the directory path that
the application should use as a default. The syntax of the pathname is
not defined, nor whether that pathname should be absolute or relative. |
Result
This function will fail (return a value of PR_FAILURE) if it cannot
allocate sufficient storage to make a copy of the path string.
PR_GetLibraryPath
PR_GetLibraryPath() allows the caller to discover the current
default.
char* PR_GetLibraryPath(void);
Result
The result is a copy of the library pathname. If sufficient storage cannot
be allocated to contain the copy, a NULL will be returned.
Storage for the result is allocated by the runtime and becomes the responsibility
of the caller. It should be deleted by calling PR_FreeLibraryName().
PR_GetLibraryName
Given a directory name and a library name construct a full path name that
will refer to the actual dynamically loaded library. This does not test
for existence of said file, it just constructs the full filename. The name
constructed is system dependent and prepared for PR_LoadLibrary().
char* PR_GetLibraryName(const char *dir, const char *lib);
Parameters
| dir |
A NULL-terminated string representing the path name of the
library. A suitable source for this information would be the result of
a call to PR_GetLibraryPath(). |
| lib |
The leaf name of the library of interest. |
Result
If the function call is successful, the character array returned
is one suitable for use in the PR_LoadLibrary()
call. The storage for the result is allocated by the runtime and becomes
the responsibility of the caller and must ultimately be deleted by using
the PR_FreeLibraryName()
function.
PR_GetLibraryName() might fail if the runtime cannot
allocate sufficient memory for the result. In such cases a NULL
will be returned.
PR_FreeLibraryName
PR_FreeLibraryName() is available for deleting the storage
allocated by the runtime in the functions described previously. It is important
to use this function to rather than calling directly into malloc in order
to isolate the runtime's semantics regarding storage management.
void PR_FreeLibraryName(char *mem);
Parameter
| mem |
A reference to a character array that was previously allocated by the
dynamic library runtime. |
PR_LoadLibrary
PR_LoadLibrary() attempts to load the referenced library.
It will suppress duplicate loading if the library is already known by the
runtime.
PRLibrary* PR_LoadLibrary(const
char *name);
Parameters
| name |
A platform dependent character array that depicts the library to be
loaded. An appropriate source of such an array would be PR_GetLibraryName(). |
Results
If the operation is successful, a reference to an opaque PRLibrary
object is returned. This becomes the library's identity. If the
library is already known to the runtime, the duplicate loading will be
suppressed. Each PR_LoadLibrary() must be paired with a
corresponding PR_UnloadLibrary()
in order to return the runtime to its original state.
If the operation fails, a NULL result will be returned. The
reason for the failure can be discovered by calling PR_GetError().
PR_UnloadLibrary
PR_UnloadLibrary() undoes the effect of a PR_LoadLibrary().
If the function is successful, future references to the library using its
identity (PRLibary*) will be invalid.
PRStatus PR_UnloadLibrary(PRLibrary
*lib);
Parameter
Result
If the function returns a value of PR_FAILURE the library could
not be unloaded. The actual reason may be discovered by calling PR_GetError().
Otherwise, future references to the library identified by its PRLibary
reference should be considered invalid.
PR_FindSymbol
PR_FindSymbol() will return an untyped reference to a symbol
in a particular library given the identity of the library and a textual
representation of the symbol in question.
void* PR_FindSymbol(PRLibrary
*lib, const char *name);
Parameters
| lib |
A valid reference to a loaded library or NULL. This parameter
can be acquired only by a call to PR_LoadLibrary().
If this parameter is NULL all libraries known to the runtime and
the main program will be searched in an unspecified order. |
| name |
A textual representation of the symbol to resolve. |
Result
PR_FindSymbol() returns an untyped pointer. Dominant use
of the function is expected to be to look up functions in a shared library,
though data symbols can also be acquired. Getting a pointer to a symbol
in a library does indicate that the library is available when the search
was made. The runtime does nothing to insure the continued validity of
the symbol. If the library is unloaded (for instance), the results of any
FindSymbol() calls become invalid as well.
PR_FindSymbolAndLibrary
PR_FindSymbolAndLibrary() finds a symbol in one of the
currently loaded libraries. Given the name of a symbol, return the address
of the symbol, and the library that contains that symbol, or NULL
if no such function can be found. The order that the known libraries are
searched in not specified.
void* PR_FindSymbolAndLibrary(const char *name, PRLibrary
**lib);
Parameters
| name |
The textual representation of the symbol to locate. |
| lib |
A reference to a location at which the runtime will store the library
in which the symbol was discovered. |
Results
If the symbol could not be found, a NULL is returned. Otherwise,
a non-NULL pointer to the symbol will be returned. Also, the owning
library's identity will be stored in the location pointed to by the parameter
lib. This function is equivalent to first calling PR_LoadLibary()
followed by PR_FindSymbol(). The identity returned from
PR_FindSymbolAndLibrary() must be the target of
a PR_UnloadLibrary() in order to return the runtime to
its original state.
Looking Up Symbols Defined in the Main Executable Program
PR_LoadLibrary cannot open a handle that references the main executable
program. (This is admittedly an omission that should be fixed.)
However, it is possible to look up symbols defined in the main executable
program as follows.
PRLibrary *lib;
void *funcPtr;
funcPtr = PR_FindSymbolAndLibrary("FunctionName",
&lib);
When PR_FindSymbolInLibrary returns, funcPtr is the
value of the function pointer you want to look up, and the variable lib
references the main executable program. Then you can call PR_FindSymbol
on lib to look up other symbols defined in the main program.
Remember to call PR_UnloadLibrary(lib) to close the library handle
when you are done.
PR_LoadStaticLibrary
The purpose of PR_LoadStaticLibrary() is so that other
clients in the process can access static symbols using the same mechanisms
as those available for dynamically loaded libraries. Once the static symbols
are made known to the runtime (presumably at initialization) the remainder
of the application can use the API uniformly, including symbols possibly
implemented in the main program.
PRLibrary* PR_LoadStaticLibrary(
const char *name, const PRStaticLinkTable
*table);
Parameters
| name |
The name the caller wishes to associate with the static library. If
the value is NULL the symbols will be made available to the library
which represents the executable. |
| table |
A reference to the client constructed table containing symbol name
and address tuples. The table is not copied by the runtime. |
Result
If the function call is successful, the new table's identity is returned.
In order to return the runtime to its previous state, the identity must
be the argument of a PR_UnloadLibarary()
call.
Platform Notes
On some platforms, in order to use the dynamic library loading functions
described in this chapter, certain environment variables must be set at
run time, and you may even need to link your executable programs using
special linker options.
This section is a short summary of these platform idiosyncrasies.
For more information, please consult the ld and dlopen
(or shl_load on HP-UX) manual pages on Unix and the LoadLibrary
documentation on Win32.
Dynamic Library Search Path
The dynamic library search path is the list of directories in which to
look for a dynamic library. Each platform has its own standard directories
in which to look for dynamic libraries, plus a customizable list of directories
specified by an environment variable.
On most Unix systems, this environment variable is LD_LIBRARY_PATH.
These systems typically use dlopen to load a dynamic library.
HP-UX uses shl_load to load dynamic libraries, and the environment
variable specifying the dynamic library search path is SHLIB_PATH.
Moreover, the executable program must be linked with the +s option
so that it will search for shared libraries in the directories specified
by SHLIB_PATH at run time. Alternatively, you can enable
the +s option as a postprocessing step using the chatr
tool:
link your executable program a.out without
the +s option
chatr +s enable a.out
On Rhapsody, the environment variable is DYLD_LIBRARY_PATH.
On Win32, the environment variable is PATH. (So the same
search path is used to search for executable programs and DLLs.)
Exporting
Symbols From the Main Executable Program
On some systems, symbols defined in the main executable program are not
exported by default. On HP-UX, one must link the executable program
with the -E linker option in order to export all symbols in the
main program to shared libraries. If you use the GNU s
(on any platform), you must also link the executable program with the -E
option.
[Contents] [Previous]
[Next][Last]
Last Updated: Tue Jul 14 17:07:28 PDT 1998
Copyright © 1998 Netscape
Communications Corporation
|