Be Dynamic: Shared Libraries in C
This is another entry into my work on C programming and working with the terminal over an IDE. Check out the rest of my articles here: https://medium.com/@TMcMac
A Quick Recap…
So what are libraries? Libraries are a programming method to keep you from having to reinvent the wheel every time you create a new program. In short, libraries are a way to store previously written functions so that new programs can access and utilize them. For a more in-depth look at libraries check out my piece on Static Libraries.
The method for creating a library of functions, of course, starts by writing out a set of useful functions! If you ever find that you are copying and pasting several functions that you have written into new programs you may want to consider adding it to a dynamic library. This is in fact how many of the most utilized libraries like stdio.h and string.h got their start. Honestly, could you imagine having to completely write out functions like printf() or scanf() every single time you were working on a new project? C programming nightmares!
Building a library
As an example, I have created several useful mathematic functions that I think I will need in the future in order to get all the simple results for two integers. I have the functions add.c, sub.c, mul.c, div.c, and mod.c which add, subtract, multiply, divide, and get the remainder of two ints respectively. Each of these functions exists in its very own c file so I have created a header called maths.h which I’ll include in my main.c file so that it can see the prototypes for each function.
To create our library in Linux we are going to first need to transform our human-readable code into what is called object code. This transformation will allow us to include the functions in our dynamic library. To complete this step we use the terminal command:
gcc -fPIC -c *.c
This command will tell our compiler, gcc, that we want to create position independent code (suitable for inclusion in a library), the -c flag tells our compiler to stop at step 3 of the compilation process which is assembly and means our output will be object or .o files, and finally, the *.c means we are including all .c files in this folder. The result of this process will be the following:
Now that we have all of our functions in assembly language it’s time to combine them in our new dynamic library. To do this we will use the command:
gcc -shared *.o -o maths.so
This command will call our gcc compiler and tell it we are making a shared file, which will contain all of our .o files, and that we want to name it (-o signify a name other than a.out) maths.so for maths shared object. The result of this will be our maths.so file. We can take a look at the objects in our library using the command nm -D maths.so as this is the names command with the object flag applied to our library file.
Finally, as we want to make sure that this library is truly dynamic and accessible to other programs we write we can check the dependencies with: ldd maths.h and if it is not currently found we can add it to the path with export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH. Now all I need to do to access my excellent simple math functions is #include <maths.h> in my new programs!
Quick look at Static Libraries
This process is a bit different from how we would create and utilize a static library. The initial step of creating useful .c files is the same, but from there, if we were creating a static library we would use: $ gcc -c *.c to create our .o files followed by:
$ ar -rc libholberton.a *.o
This command includes ar which is short for achiever and has the flags r and c. The c flag tells the archiver to create the file named libholberton.a and then to insert the objects (our .o files), replacing older files where needed (thanks to the r flag). Finally, for a static library, we would use: ranlib libholberton.a to create an index of objects in our libholberton.a archive.
Dynamic vs Static
This article has been about creating a dynamic library rather than a static one. If you want to learn about creating a static library you should go check out my other article on how to do just that. The quick version of why you would want one or the other for a given situation is this. A static library is great if you want to include all the code in a single file as a static library is literally included in its entirety at compilation. The compiler will see the include message at the top of your new program and will add all of the libraries in binary code to the top of your program. The advantage to this is that the program will work remotely as a single file. The disadvantage is that if your program is large and includes a lot of libraries it can ballon to very large very quickly. On the other side of things, Dynamic Libraries are only called on when the program is executed. This can lead to much smaller programs that run faster and take up less space on your, or your client’s computers, but there is a cost in complexity. You will need to maintain multiple files, or your client will need to download a whole package of libraries to make sure your program can run on their machine. It’s really situation dependent on which form you want to use for your programming but if you’ve read both my pieces you now have both options in your tool kit!
Thanks for reading and happy coding!