NSPR Reference: Chapter 22 Dynamic Library Linking
Description: The Sun-Netscape Alliance, a strategic alliance formed by America Online and Sun Microsystems, Inc., is delivering iPlanet e-commerce software and enterprise solutions that enable companies to compete successfully in the Net Economy
Keywords: electronic commerce, ecommerce, ebusiness, e-business, e-commerce, enterprise software, net economy, Netscape, Sun Microsystems, Sun-Netscape Alliance, iPlanet, internet software

NSPR Reference Previous Contents Next

## Chapter 22 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 to condition symbols of statically linked code so that to other clients it appears as though they are dynamically loaded.

Library Linking Types
Library Linking Functions
Platform Notes

## Library Linking Types

These data types are defined for dynamic library linking:

`PRLibrary``
` `PRStaticLinkTable```

#### PRLibrary

A `PRLibrary` is an opaque structure. A reference to such a structure can 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 can 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;

## Library Linking Functions

The library linking functions are:

`PR_SetLibraryPath``
` `PR_GetLibraryPath``
` `PR_GetLibraryName``
` `PR_FreeLibraryName``
` `PR_LoadLibrary``
` `PR_UnloadLibrary``
` `PR_FindSymbol``
` `PR_FindSymbolAndLibrary```

#### PR_SetLibraryPath

Registers a default library pathname with a runtime.

##### Syntax

    PRStatus PR_SetLibraryPath(const char *path);

##### Parameters

The function has this parameter:

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.

##### Returns

The function returns one of the following values:

If successful, `PR_SUCCESS`.

- If unsuccessful, `PR_FAILURE`. This may indicate that the function cannot allocate sufficient storage to make a copy of the `path` string

##### Description

This function registers a default library pathname with the runtime. This allows an environment to express policy decisions globally and lazily, rather than hardcoding and distributing the decisions throughout the code.

#### PR_GetLibraryPath

Retrieves the current default library path.

##### Syntax

    char* PR_GetLibraryPath(void);

##### Parameters

The function has no parameters.

##### Returns

A copy of the default library pathname string. In case of error, returns `NULL`.

##### Description

This function retrieves the current default library pathname, copies it, and returns the copy. If sufficient storage cannot be allocated to contain the copy, the function returns `NULL`. Storage for the result is allocated by the runtime and becomes the responsibility of the caller. When it is no longer used, free it using `PR_FreeLibraryName`.

#### PR_GetLibraryName

Constructs a full library path name.

##### Syntax

    char* PR_GetLibraryName (
       const char *dir,
       const char *lib);

##### Parameters

The function has these parameters:

`dir` | A `NULL`-terminated string representing the path name of the library, as returned by `PR_GetLibraryPath`.
`lib` | The leaf name of the library of interest.

##### Returns

If successful, returns a new character string containing a constructed path name. In case of error, returns `NULL`.

##### Description

This function constructs a full path name from the specified directory name and library name. The constructed path name refers to the actual dynamically loaded library. It is suitable for use in the `PR_LoadLibrary` call.

This function does not test for existence of the specified file, it just constructs the full filename. The way the name is constructed is system dependent.

If sufficient storage cannot be allocated to contain the constructed path name, the function returns `NULL`. Storage for the result is allocated by the runtime and becomes the responsibility of the caller. When it is no longer used, free it using `PR_FreeLibraryName`.

#### PR_FreeLibraryName

Frees memory allocated by NSPR for library names and path names.

##### Syntax

    void PR_FreeLibraryName(char *mem);

##### Parameter

The function has this parameter:

`mem` | A reference to a character array that was previously allocated by the dynamic library runtime.

##### Returns

Nothing.

##### Description

This function deletes 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.

#### PR_LoadLibrary

Loads a referenced library.

##### Syntax

    PRLibrary* PR_LoadLibrary(const char *name);

##### Parameters

The function has this parameter:

`name` | A platform-dependent character array that names the library to be loaded, as returned by `PR_GetLibraryName`.

##### Returns

If successful, returns a reference to an opaque `PRLibrary` object.

If the operation fails, returns `NULL`. Use `PR_GetError` to find the reason for the failure.

##### Description

This function loads and returns a reference to the specified library. The returned reference becomes the library's identity. The function suppresses duplicate loading if the library is already known by the runtime.

Each call to `PR_LoadLibrary` must be paired with a corresponding call to `PR_UnloadLibrary` in order to return the runtime to its original state.

#### PR_UnloadLibrary

Unloads a library loaded with `PR_LoadLibrary`.

##### Syntax

    PRStatus PR_UnloadLibrary(PRLibrary *lib);

##### Parameter

The function has this parameter:

`lib` | A reference previously returned from `PR_LoadLibrary`.

##### Returns

The function returns one of the following values:

If successful, `PR_SUCCESS`.

- If unsuccessful, `PR_FAILURE`. Use `PR_GetError` to find the reason for the failure.

##### Description

This function undoes the effect of a `PR_LoadLibrary`. After calling this function, future references to the library using its identity as returned by `PR_LoadLibrary` will be 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.

##### Syntax

    void* PR_FindSymbol (
       PRLibrary *lib,
       const char *name);

##### Parameters

The function has these parameters:

`lib` | A valid reference to a loaded library, as returned by `PR_LoadLibrary`, or `NULL`.
`name` | A textual representation of the symbol to resolve.

##### Returns

An untyped pointer.

##### Description

This function finds and returns an untyped reference to the specified symbol in the specified library. If the `lib` parameter is `NULL`, all libraries known to the runtime and the main program are searched in an unspecified order.

Use this function to look up functions or data symbols in a shared library. 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 ensure the continued validity of the symbol. If the library is unloaded, for instance, the results of any `PR_FindSymbol` calls become invalid as well.

#### PR_FindSymbolAndLibrary

Finds a symbol in one of the currently loaded libraries, and returns both the symbol and the library in which it was found.

##### Syntax

    void* PR_FindSymbolAndLibrary (
       const char *name,
       PRLibrary **lib);

##### Parameters

The function has these 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. This location must be pre-allocated by the caller.

##### Returns

If successful, returns a non-`NULL` pointer to the found symbol, and stores a pointer to the library in which it was found at the location pointed to by `lib`.

If the symbol could not be found, returns `NULL`.

##### Description

This function finds the specified symbol in one of the currently loaded libraries. It returns the address of the symbol. Upon return, the location pointed to by the parameter `lib` contains a pointer to the library that contains that symbol. The location must be pre-allocated by the caller.

The function returns `NULL` if no such function can be found. The order in which the known libraries are searched in not specified.This function is equivalent to calling first `PR_LoadLibrary`, then `PR_FindSymbol`.

The identity returned from this function must be the target of a `PR_UnloadLibrary` in order to return the runtime to its original state.

##### Finding 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_FindSymbolAndLibrary` returns, `funcPtr` is the value of the function pointer you want to look up, and the variable `lib` references the main executable program. You can then 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.

## Platform Notes

To use the dynamic library loading functions on some platforms, certain environment variables must be set at run time, and you may need to link your executable programs using special linker options.

This section summarizes these platform idiosyncrasies. For more information, consult the man pages for `ld` and `dlopen` (or `shl_load` on HP-UX) for Unix, and the `LoadLibrary` documentation for Win32.

Dynamic Library Search Path
Exporting Symbols from the Main Executable Program

### 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. For example, link your executable program `a.out` without the `+s` option, then execute the following:

      chatr +s enable a.out

- On Rhapsody, the environment variable is`DYLD_LIBRARY_PATH`.

- On Win32, the environment variable is `PATH`. 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, you 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 compiler`s` (on any platform), you must also link the executable program with the `-E` option.

Previous Contents Next

Last Updated May 18, 2001