How to create and use Dynamic Libraries in C language
Description of libraries
A library is an assembly of pre-compiled pieces of code that can be reused in a program. Normally the library is indexed, so it is easy to find symbols (functions, variables and so on) in them. For this reason, linking a program whose object files are ordered in libraries is faster than linking a program whose object files are separate on the disk. Also, when using a library, we have fewer files to look for and open, which even further speeds up linking. There are two kinds of libraries — static libraries and dynamic (shared) libraries.
Static libraries are just collections of object files that are linked into the program during the linking phase of compilation and are not relevant during runtime. This last comment seems obvious, as we already know that object files are also used only during the linking phase and are not required during runtime — only the program’s executable file is needed to run the program.
Shared libraries (also called dynamic libraries) are linked into the program in two stages. First, during compile time, the linker verifies that all the symbols (again, functions, variables, and the like) required by the program, are either linked into the program, or in one of its shared libraries. However, the object files from the dynamic library are not inserted into the executable file. Instead, when the program is started, a program in the system (called a dynamic loader) checks out which shared libraries were linked with the program, loads them to memory, and attaches them to the copy of the program in memory.
Differences between static and dynamic libraries?
In the next chart you can see some of the differences between static and dynamic (shared) libraries.
Advantages and drawbacks of static and dynamic libraries
Some advantages of shared libraries are as follows:
· Load time might be reduced because the shared library code might already be in memory.
· Run-time performance can be enhanced because the operating system is less likely to page out shared library code that is being used by several applications, or copies of an application, rather than code that is only being used by a single application. As a result, fewer page faults occur.
· The routines are not statically bound to the application but are dynamically bound when the application is loaded. This permits applications to automatically inherit changes to the shared libraries, without recompiling or rebinding.
Disadvantages of dynamic linking include the following:
· From a performance viewpoint, there is “glue code” that is required in the executable program to access the shared segment. There is a performance cost in references to shared library routines of about eight machine cycles per reference. Programs that use shared libraries are usually slower than those that use statically-linked libraries.
· A more subtle effect is a reduction in “locality of reference.” You may be interested in only a few of the routines in a library, and these routines may be scattered widely in the virtual address space of the library. Thus, the total number of pages you need to touch to access all of your routines is significantly higher than if these routines were all bound directly into your executable program. One impact of this situation is that, if you are the only user of these routines, you experience more page faults to get them all into real memory. In addition, because more pages are touched, there is a greater likelihood of causing an instruction translation lookaside buffer (TLB) miss.
· When a program references a limited number of procedures in a library, each page of the library that contains a referenced procedure must be individually paged into real memory. If the procedures are small enough that using static linking might have linked several procedures that are in different library pages into a single page, then dynamic linking may increase paging thus decreasing performance.
· Dynamically linked programs are dependent on having a compatible library. If a library is changed (for example, a new compiler release may change a library), applications might have to be reworked to be made compatible with the new version of the library. If a library is removed from the system, programs using that library will no longer work.
In statically-linked programs, all code is contained in a single executable module. Library references are more efficient because the library procedures are statically linked into the program. Static linking increases the file size of your program, and it may increase the code size in memory if other applications, or other copies of your application, are running on the system.
How dynamic libraries work
In the diagram below, you will see how a dynamic library works
How to create a dynamic library
To create a dynamic library, you need the *.c files that you need in your executable program. Next, using those files, you create the object files. For that you use the following command.
gcc -Wall -fPIC -c *.c
Where:
gcc is a collection of programming compilers used in C to compile files.
-Wall is the flag used to show all the warning messages.
-fPIC flag generates position-independent code, which accesses all constant address stored in the Global Offset Table (GOT).
-c creates the object file .o.
*.c is a command that says to the compiler to use all the .c files inside the current folder.
After you run the above command, you will have the same amount of object files (.o) as the amount of c files. The next step is creating the dynamic library. This kind of libraries are files with the extension .so. The command required to create a dynamic library is the following:
gcc -shared -Wl,-soname,libname.so -o libname.so *.o
Where:
gcc is a collection of programming compilers used in C to compile files.
-shared flag is used to the compiler to compile the files into a dynamic library. Also, Produce a shared object which can then be linked with other objects to form an executable.
-Wl,options passes options to linker: in this case, -soname, to indicate the binary api compatibility of the library (0, by default). In this part, you can replace the word libname for the name of the library you want to set.
-o flag saves the output library in a file with a given name. In this case, libname.so. It is important to make sure that the name set next to the soname is the same that you are using in this part of the command.
*.o is a command that says to the compiler to use all the .o files inside the current folder.
If you want to check what is inside the dynamic library, you can use the following command:
nm -D libdynamic.so
Then, you will observe a similar response to the following picture:
Using Dynamic Libraries (Linux)
Once you finish the creation of your library, it is ready to use. Now you need a program done in C in which you can find the functions that you previous created and are also included in the dynamic library that you just created. We will call this c file test.c. Finally, you need to name the executable program that you are going to create using the test.c file and the dynamic library. We will call this program execution. execution. Below you can find the command needed to create the executable program.
gcc -Wall -pedantic -Werror -Wextra -L. test.c -ldynamic -o execution
Where:
gcc is a collection of programming compilers used in C to compile files.
-Wall is the flag used to show all the warning messages.
-pedantic is the flag used to issue all the warnings demanded by strict ISO C and ISO C++; reject all programs that use forbidden extensions, and some other programs that do not follow ISO C and ISO C++.
-Werror is the flag used to make all warnings into errors.
-Wextra is the flag used to print extra warning messages for various events.
-L flag tells the compiler to look in the current directory for the library file.
-test.c is the C file with in which the functions created are implemented
-l searches the library named dynamic when linking and the directories searched include several standard system directories plus any that you specify with -L.
-o flag saves the output library in a file with a given name. In this case, execution.
-execution is the name of the executable file
The final step is to export the library to the environment. For that purpose, you enter the following command:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
LD_LIBRARY_PATH is a environment variable that lists directory where executable can search for linux shared library. It’s also called the shared library search path.
The value of the environment variable LD_LIBRARY_PATH is a colon-separated (:) set of directories where libraries are searched for first before the standard set of directories.
After this you can check inside the executable file (execution is the example).
ldd execution
Finally, now you can execute your program properly using the following command:
./execution
Sources
(Don´t go out without checking these amazing sources)