Everything you need to know to start using C libraries

Sech Rueda
7 min readJul 15, 2019

--

Understanding as much as we can about c libraries is a priority that a good programmer must have.

Why are c libraries so important? , why would you use a c library?

I will start explaning this with one simple question:

Do you believe that every programmer is going to create its own versión of a print function to print something?

Actually we are fully capable of, but this would not be clever in order to optimize time. This is what basically libraries are for, to not “reinvent the wheel”. One of the most important reasons we use libraries is for this, to store commonly used functions without having to created them again from 0

What are c libraries?

To make it simple and easy for us, we got to know that a librarie is JUST A FILE and this file contains something called object files. That are no more than low level instructions which can be understood by the computer or “machine code”. Of course this object file comes from compiling a “.c” file till the assembling part, so the linking stage is simply not done.

How c libraries work?

So in order to know how they work, we have to know that there are 2 types of libraries depending on the way i link them to my program.

Linking statically (Static Library): This means attaching identical copies of the modules from the library to our main module. One could say that if we link statically or use a static library we are insirting copies of code into my program.

Linking dinamically (Shared or Dinamyc Library): This means to reference what i need from the library and use it when needed but without adding or attaching any extra code to our main module.

Having this clear we can think on andvantages or disadvantage of each one depending on what are the needs.

For example we can conclude that if we use a static library our executable file (program) is going to weigh so much more because we are adding more code to our main.

By the other hand imaging that you are going to give your app or program to a costumer, you can decide wether to say:

“Here is your app and this is the only think you need”

or

“Here is your app but you have to install this 100 libraries in order to run it”

So this will depend on the context and the needs at the end.

from “Differences between static and dynamic libraries” by Brian Chew

How do we create a c library?

To create a Static library

from http://docencia.ac.upc.edu/FIB/USO/Bibliografia/unix-c-libraries.html#creating_static_archive

“The basic tool used to create static libraries is a program called 'ar', for 'archiver'. This program can be used to create static libraries (which are actually archive files), modify object files in the static library, list the names of object files in the library, and so on. In order to create a static library, we can use a command like this”:

ar rc libmylibrary.a objectfile1.o objectfile2.o

This command will create a library called libmylibrary and put on it copies of the object files objectfile1 and objectfile2.

“If the library file already exists, it has the object files added to it, or replaced, if they are newer than those inside the library. The 'c' flag tells ar to create the library if it doesn't already exist. The 'r' flag tells it to replace older object files in the library, with the new object files.”

The “.a” extension corresponds to “archive” and this is the extension for static libraries in linux. This will change a little depeding on the operating system. For example, on Windows static libraries typically have a “.lib” extension.

To create a Shared library

from http://docencia.ac.upc.edu/FIB/USO/Bibliografia/unix-c-libraries.html#creating_static_archive

The creation of a shared library is rather similar to the creation of a static library. Compile a list of object files, then insert them all into a shared library file. However, there are two major differences:

  1. Compile for “Position Independent Code” (PIC) — When the object files are generated, we have no idea where in memory they will be inserted in a program that will use them. Many different programs may use the same library, and each load it into a different memory in address. Thus, we need that all jump calls (“goto”, in assembly speak) and subroutine calls will use relative addresses, and not absolute addresses. Thus, we need to use a compiler flag that will cause this type of code to be generated.
    In most compilers, this is done by specifying '-fPIC' or '-fpic' on the compilation command.
  2. Library File Creation — unlike a static library, a shared library is not an archive file. It has a format that is specific to the architecture for which it is being created. Thus, we need to use the compiler (either the compiler’s driver, or its linker) to generate the library, and tell it that it should create a shared library, not a final program file.
    This is done by using the '-G' flag with some compilers, or the '-shared' flag with other compilers.

Thus, the set of commands we will use to create a shared library, would be something like this:

cc -fPIC -c util_file.c
cc -fPIC -c util_net.c
cc -fPIC -c util_math.c
cc -shared libutil.so util_file.o util_net.o util_math.o

The first three commands compile the source files with the PIC option, so they will be suitable for use in a shared library (they may still be used in a program directly, even thought they were compiled withPIC). The last command asks the compiler to generate a shared library.

The “.so” extension correspond to “shared object” and this extension is used in linux. On Windows, dynamic libraries typically have a “.dll” (dynamic link library) extension.

How to use c libraries ?

In order to use them we need to know understad in which step of the compilation proccess they act.

When we use a static librarary, we use make use of it in the compyling proccess because we made kind of a “copy and paste” everything we need into our main module so after doing it we dont need it anymore.

from Static vs Shared Libraries

On the other hand when we use a shared library we actually have it in 2 moments.

  1. Compile Time — here we need to tell the linker to scan the shared library while building the executable program, so it will be convinced that no symbols are missing. It will not really take the object files from the shared library and insert them into the program.
  2. Run Time — when we run the program, we need to tell the system’s dynamic loader (the process in charge of automatically loading and linking shared libraries into the running process) where to find our shared library.

Using Static libraries

from http://docencia.ac.upc.edu/FIB/USO/Bibliografia/unix-c-libraries.html#creating_static_archive

After we created our archive, we want to use it in a program. This is done by adding the library’s name to the list of object file names given to the linker, using a special flag, normally '-l'. Here is an example:

cc main.o -L. -lutil -o prog

This will create a program using object file "main.o", and any symbols it requires from the "util" static library. Note that we omitted the "lib" prefix and the ".a" suffix when mentioning the library on the link command. The linker attaches these parts back to the name of the library to create a name of a file to look for. Note also the usage of the '-L' flag - this 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.

Using Dynamic libraries

from http://docencia.ac.upc.edu/FIB/USO/Bibliografia/unix-c-libraries.html#creating_static_archive

The compilation part is easy. It is done almost the same as when linking with static libraries:

cc main.o -L. -lutil -o prog

The linker will look for the file 'libutil.so' (-lutil) in the current directory (-L.), and link it to the program, but will not place its object files inside the resulting executable file, 'prog'.

The run-time part is a little trickier. Normally, the system’s dynamic loader looks for shared libraries in some system specified directories (such as /lib, /usr/lib, /usr/X11/lib and so on). When we build a new shared library that is not part of the system, we can use the 'LD_LIBRARY_PATH' environment variable to tell the dynamic loader to look in other directories. 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 you have this variable defined, try:

echo $LD_LIBRARY_PATH

If you get a message such as 'LD_LIBRARY_PATH: Undefined variable.', then it is not defined.

To know how to define this variable and in its 4 cases go to: http://docencia.ac.upc.edu/FIB/USO/Bibliografia/unix-c-libraries.html#creating_static_archive

And finally you can check if the system locates the library properly for a given program linked with this library:

ldd prog

--

--

Sech Rueda

FullStack Developer emphasized on Back-End and DevOps engineering