Dynamic libraries

Ana-Morales
4 min readSep 7, 2020

In a past post, which you can find in this link https://medium.com/@Ana_Morales/c-static-libraries-479afec201a6, we talked about static libraries. This time we are going to talk about dynamic libraries. But first let’s remember what libraries are.

What is a library and why to use it?

Libraries are a simple and versatile way to modularize and reuse code. A library is essentially a set of functions and / or procedures. Libraries allow encapsulating functionality, which may then be available in different programs. For this encapsulated functionality to be used, the program that requires it must be in charge of linking the library that contains it. Libraries can be classified into two large families: Static Libraries and Dynamic Libraries.

Dynamic libraries

Shared libraries are also known as dynamic libraries and we can see them in Linux like .so (shared object) files. These libraries are linked into the program in two steps. During compile time, the linker verifies that all the functions, variables and so on, required by the program, are either linked into the program, or in one of its shared libraries. But the object files from the dynamic library are not inserted into the executable file. Instead, When the application is running, and only then, the dynamic loader checks which shared libraries were linked to the program, loads them into memory, and attaches them to the copy of the program in memory.

Creating a Dynamic Library

  1. First we need to create the object files (.o). For this we need to compile our library source code (.c) into position-independent code (PIC), so we must use the compiler flag -fPIC and the -c option in Linux gcc. The line showed below will create the object files for all the .c files in the current directory.
$ gcc -c -fPIC *.c

So if we have the next .c files in the current directory:

myfunction1.c myfunction2.c myfunction3.c

after we pass gcc -c -fPIC *.c we are going to have:

myfunction1.c myfunction2.c myfuntion3.cmyfunction1.o myfunction2.o myfunction3.o

2. Create the dynamic library (.so). We need to use the compiler to generate the library and tell it that it should create a shared library, not a final program file. We can do this using the -shared flag. The next line will create a dynamic library named “libmylibrary.so”:

$ gcc -shared -o libmylibrary.so *.o

Using a dinamyc library

We use the dynamic library through two steps:

  • Compile time. We must tell the linker to scan the shared library while making the executable program, so that it is sure there are no missing symbols. It won’t actually take the object files from the shared library and insert them into the program.
    To do this in Linux gcc, the -L argument is used to define the path, and -l is used for the library name without the “lib” prefix and without the “.so” suffix. Here is an example:
$ gcc main.c -L. -lmylibrary -o program1

The linker will look for the file ‘libmylibrary.so’ (-lmylibrary).

The usage of the -L flag, tells the linker that libraries might be found in the given directory (.”, refering to the current directory), in addition to the standard locations where the compiler looks for system libraries. The linker will link the file libmylibrary.so to the program but will not place its object files inside the resulting executable file, 'program1'.

  • Run time. When we run the program we need to give the loader a little help to find the shared library. We can use the environment variable LD_LIBRARY_PATH for this. The way to do that depends on the type of shell we use (‘tcsh’ and ‘csh’, versus ‘sh’, ‘bash’, ‘ksh’ and similar shells), as well as on whether or not “LD_LIBRARY_PATH” is already defined. To check if this variable is defined, we type:
$ echo $LD_LIBRARY_PATH

If we get a message like ‘LD_LIBRARY_PATH: Undefined variable.', then it is not defined.

So, to define this variable in ‘sh, ‘bash, or similar we type:

$ export LD_LIBRARY_PATH= /full/path/to/library/directory:$LD_LIBRARY_PATH

Now we can check if the system locates the library properly for a given program linked with this library like this:

$ ldd program1

Static libraries vs. Dynamic libraries

Static Libraries:

  • A static library is “inserted” within our executable, which means that we can take it to another computer without fear of missing libraries.
  • But if the libraries have a bug and a version appears that fixes that bug, you have to recompile the code
  • The executable is larger because they have the libraries included within the executable.
  • These are faster to execute because the functions are inside the executable, so we don’t have to look for them.

Dynamic libraries:

  • A dynamic library is not inserted into our executable so our executable will be smaller.
  • But if we take our executable to another machine, the libraries have to go with it.
  • The execution is slower because the library must be searched outside the executable.
  • If there is a bug in the library and a version appears that fixes that bug, this is updated and fixed in all executables that use it.

--

--