HPlogo HP C++ Programmer's Guide: HP 9000 Series Workstations and Servers > Chapter 3 Compiling and Executing HP C++ Programs

Creating and Using Shared Libraries

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

This section provides information about shared libraries that is specific to HP C++. For additional information about creating and using shared libraries, see the manual HP-UX Linker and Libraries Online User Guide. For information on using the options to the CC command, see Table 3-1 “The CC Command Options” in this chapter.

Compiling for Shared Libraries

To create a C++ shared library, you must first compile your C++ source with either the +z or +Z option. These options create object files containing position-independent code (PIC).

Creating a Shared Library

To create a shared library from one or more object files, use the -b option at link time. (The object files must have been compiled with +z or +Z.) The -b option creates a shared library rather than an executable file.

NOTE: You must use the CC command to create a C++ shared library. This is because the CC command ensures that any static constructors and destructors in the shared library are executed at the appropriate times.

Using a Shared Library

To use a shared library, you simply include the name of the library on the CC command line as you would with an archive library, or use the -l option, as with other libraries. The linker links the shared library to the executable file it creates. Once you create an executable file that uses a shared library, you must not move the shared library or the dynamic loader (dld.sl(5)) will not be able to find it.

NOTE: You must use the CC command to link any program that uses a C++ shared library. This is because the CC command ensures that any static constructors and destructors in the shared library are executed at the appropriate times.

Example

The following command compiles the two files Strings.C and Arrays.C and creates the two object files Strings.o and Arrays.o. These object files contain position-independent code (PIC):

CC -c +z Strings.C Arrays.C

The following command builds a shared library named libshape.sl from the object files Strings.o and Arrays.o:

CC -b -o libshape.sl Strings.o Arrays.o

The following command compiles a program, draw_shapes.C, that uses the shared library, libshape.sl:

CC draw_shapes.C libshape.sl

Linking Archive or Shared Libraries

If both an archive and shared version of a particular library reside in the same directory, the linker links in the shared version by default. You can override this behavior with the -a linker option. This option tells the linker which type of library to use. The -a option is positional and applies to all subsequent libraries specified with the -l option until the end of the command line or until the next -a option is encountered.

The syntax of this option when used with CC is:

-Wl,-a [archive ] [shared ] [default]

The different meanings of this option are:

-Wl,-a,archive

Select archive libraries. If the archive library does not exist, the linker generates a warning message and does not create the output file.

-Wl,-a,shared

Select shared libraries. If the shared library does not exist, the linker generates a warning message and does not create the output file.

-Wl,-a,default

Select the shared library if it exists; otherwise, select the archive library.

The following example directs the linker to use the archive version of the library libshape, followed by standard shared libraries if they exist; otherwise select archive versions.

CC box.o sphere.o -Wl,-a,archive -lshape -Wl,-a,default

Updating a Shared Library

The CC command cannot replace or delete object modules in a shared library. To update a C++ shared library, you must recreate the library with all the object files you want the library to include. If, for example, a module in an existing shared library requires a fix, simply recompile the fixed module with the +z or +Z option, then recreate the shared library with the -b option. Any programs that use this library will now be using the new versions of the routines. That is, you do not have to relink any programs that use this shared library because they are attached at run time.

Forcing the Export of Symbols in main

By default, the linker exports from a program only those symbols that were imported by a shared library. For example, if an executable's shared libraries do not reference the program's main routine, the linker does not include the main symbol in the a.out file's export list. Normally, this is a problem only when a program explicitly calls shared library management routines. (See "Routines You Can Use to Manage C++ Shared Libraries" later in this chapter.) To make the linker export all symbols from a program, use the -Wl,-E option which passes the -E option to the linker.

Binding Times

Because shared library routines and data are not actually contained in the a.out file, the dynamic loader must attach the routines and data to the program at run time. To accelerate program startup time, routines in a shared library are not bound until referenced. (Data items are always bound at program startup.) This deferred binding distributes the overhead of binding across the total execution time of the program and is especially helpful for programs that contain many references that are not likely to be executed.

Forcing Immediate Binding

You can force immediate binding, which forces all routines and data to be bound at startup time. With immediate binding, the overhead of binding occurs only at program startup time, rather than across the program's execution. Immediate binding also detects unresolved symbols at startup time, rather than during program execution. Another use of immediate binding is to get better interactive performance, if you don't mind program startup taking longer. To force immediate binding, use the option -Wl,-B,immediate. For example,

CC -Wl,-B,immediate draw_shapes.o -lshape

To get the default binding, use -Wl,B,deferred. For more information, see HP-UX Linker and Libraries Online User Guide.

Side Effects of C++ Shared Libraries

When you use C++ shared libraries, all constructors and destructors of nonlocal static objects in the library execute. This is different from C++ archive libraries where only the constructors and destructors in object files you actually use are executed.

Routines You Can Use to Manage C++ Shared Libraries

You can call any of several routines to explicitly load and unload shared libraries, and get information about shared libraries. Refer to HP-UX Linker and Libraries Online User Guide for information about these routines.

HP C++ provides the following additional routines for managing C++ shared libraries:

cxxshl_load()

Explicitly loads a shared library and executes any constructors for nonlocal static objects if they exist. This routine is identical to the general shl_load() routine except that it also executes appropriate constructors. See HP-UX Linker and Libraries Online User Guide for information about shl_load(), including syntax.

cxxshl_load() can be used on non-C++ shared libraries and can be called from other languages.

cxxshl_unload()

Executes the destructors for any constructed nonlocal static objects and unloads the shared library. This routine is identical to the general shl_load() routine except that it also executes appropriate destructors. See HP-UX Linker and Libraries Online User Guide for information about shl_load(), including syntax. cxxshl_unload() can be used on non-C++ shared libraries and can be called from other languages.

When you use either of these routines, be sure to compile with the -ldld option to link them in.

Shared Library Header files

The C++ shared library management routines (cxxshl_load() and cxxshl_unload()) use special data types and constants defined in the header file /usr/include/CC/cxxdl.h (/opt/CC/include/cxxdl.h for HP-UX 10.x C++ versions). When using these functions from a C++ program be sure to include cxxdl.h:

#include <cxxdl.h>

If an error occurs when calling shared library management routines, the system error variable, errno, is set to an appropriate error value. Constants are defined for these error values in /usr/include/errno.h (see errno(2)). Thus, if a program checks for these values, it must include errno.h:

#include <errno.h>

Version Control in Shared Libraries

You can create different versions of a routine in a shared library with the HP_SHLIB_VERSION pragma. HP_SHLIB_VERSION assigns a version number to a module in a shared library. The version number applies to all global symbols defined in the module's source file. The syntax of this pragma is:

#pragma HP_SHLIB_VERSION ["]date["]

The date argument is of the form month/year. The month must be 1 through 12, corresponding to January through December. The year can be specified as either the last two digits of the year (92 for 1992) or a full year specification (1992). Two-digit year codes from 00 through 40 represent the years 2000 through 2040.

This pragma should only be used if incompatible changes are made to a source file. If a version number pragma is not present in a source file, the version number of all symbols defined in the object module defaults to 1/90. For more information about version control in shared libraries, see HP-UX Linker and Libraries Online User Guide.

Adding New Versions to a Shared Library

To rebuild a shared library with new versions of some of the object files, use the CC command and the -b option with the old object files and the newly compiled object files. The new source files should use the HP_SHLIB_VERSION pragma.

For example, suppose the source file box.C has been compiled into the shared library libshape.sl. Further suppose you want to add new functionality to functions in box.C, making them incompatible with existing programs that call libshape.sl. Before making the changes, make a copy of the existing box.C and name it oldbox.C. Then change the routines in box.C, using the version pragma specifying the current month and year. The following illustrates these steps:

cp box.C oldbox.C Save the old source.

mv box.o oldbox.o Save the old object file.

   .

   .

   .     Change box.C to create the new version.



#pragma HP_SHLIB_VERSION "9/92"  // Date is September 1992.

// This is a new version of the box class, in box.C.

            box::box() {...}

To update the shared library, libshape.sl, to include the new box.C routines, compile box.C and rebuild the library with the new box.o and oldbox.o:

CC -c +z box.C

CC -b -o libshape.sl oldbox.o sphere.o box.o

Thereafter, any programs linked with libshape.sl use the new versions of the box.C routines. Programs linked with the old version still use the old versions.

© Hewlett-Packard Development Company, L.P.