Functions are blocks of code that are reusable throughout a program. Using them saves time, removing the need to rewrite code multiple times. Libraries, like functions also save time in that they make functiones reusable in multiple programs.
Static libraries, while reusable in multiple programs, are locked into a program at compile time. Dynamic, or shared libraries on the other hand, exist as separate files outside of the executable file.
The downside of using a static library is that it’s code is locked into the final executable file and cannot be modified without a re-compile. In contrast, a dynamic library can be modified without a need to re-compile.
Because dynamic libraries live outside of the executable file, the program need only make one copy of the library’s files at compile-time. Whereas using a static library means every file in your program must have it’s own copy of the library’s files at compile-time.
The downside of using a dynamic library is that a program is much more susceptible to breaking. If a dynamic library for example becomes corrupt, the executable file may no longer work. A static library, however, is untouchable because it lives inside the executable file.
The upside of using a dynamic library is that multiple running applications can use the same library without the need for each to have it’s own copy.
Another benefit of using static libraries is execution speed at run-time. Because the it’s object code (binary) is already included in the executable file, multiple calls to functions can be handled much more quickly than a dynamic library’s code, which needs to be called from files outside of the executable.
What does this mean in practical terms? Well, imagine you’re a devloper who has issued an application to thousands of users. When you want to make a few updates to the app, would you rather have to re-issue the entire program, or would you rather just issue updates in the form of modified libraries? The answer depends on the downsides your application can afford. If you have a lot of files, multiple copies of a static library means an increase in the executable file’s size. If, however, the benefits of execution time outweigh the need to save space, the static library is the way to go.
How to create a Dynamic Library
The way to create a Dynamic Library in Linux is with the
gcc command using the
-c to generate the object files (.o) from the source files (.c) and the
-fPIC to make the code position independent. Thus, the following command makes a bunch of .o files from each .c file in the current directory (You can select which functions you want for your library).
gcc -c -fPIC *.c
Next, we are going to put together those objects files into one library. To do this as a Dynamic Library we also use
gcc but with the
-shared option. The
-o is to specify the name of the file you want it to have.
gcc -shared -o liball.so *.o
This way you must have your library created. To verify that you did it and have the right functions as dynamic symbols you can use:
nm -D liball.so
Great! at this point, you have your Dynamic Library created!
How to use it
Now, you have to compile the library with your main.c file to link it and use it as you want. For this to work, you have to add the location of your library files into the environmental variable to know where to find the functions.
Then, you can compile it by typing the following:
gcc -L . 0-main.c -l all -o example
How to Create a Static Library
The command to create a static library is
ar, which means “archiver.” The
ar command doesn’t just create static libraries (which are basically archive files). It can also list the names of object files in the library and modify
.o files contained in the static library. If you’ve ever used a
.zip or a
.tar file, you know how easy it is to create a file that contains other files. That is exactly what a
.a archive file is: a file containing other files. To create object files, simply type and execute
gcc -c *.c. This command tells the compiler to generate object files for all the
.c files in the current directory. In order to create a static library, we can use the following command:
ar rc libholberton.a *.o
In this command, the
r flag ensures that older files will be updated by being replaced with new object files. The
c flag means that the library will be created if it does not already exist. Finally, the
*.o is a wildcard operation to include all files ending with
.o in the static library. It is important to note the format for naming a
At this point, you can store your archive in a library directory. For instance, some coders like to store archives in a standard directory once they are sure that it works. On Linux and Mac the
usr/local/lib directory is a good choice because that is the directory set aside for the user’s custom libraries.
Using Static Libraries
The point of creating a static library is to use it with other programs. If your library is in a standard directory, then you can compile your code as follows:
gcc test_code.c -lholberton -o test_code
In the above command it is worth noting that your source code,
test_code.c in this case, needs to be listed before the
-l flag. The expression,
-l combined with
holberton tells the compiler to look for an archive called libholberton.a. This is why it is important to use the standard format for naming that I described earlier. For instance if
test_code.c was the following:
Typing and executing
gcc test_code.c -lholberton -o test_code would generate an executable file called
test_code. In order to accomplish this, the compiler looks through the library that is specified with the
-l flag for the
_puts function object code. Executing
test_code like so:
./test_code would give us the following output:
Hello World!. Now that you know how to create and use static libraries, I hope you have fun coding!
Bonus: Use it in Python
With Python you can import the libraries you create in C, all you have to do is import ctypes and use
CDDLL just like this:
spam = ctypes.CDLL(‘./liball.so’)
Then you can use your previously created functions as you want. Let’s say that you want to call a function called sum_rest from your library, then you can call it as spam.sum_rest