C static library
How does a static library work?
Static libraries are .a files (or in Windows .lib). All the code related to the library is in this file and is directly linked to the program at compile time. A program that uses a static library takes copies of the code it uses from the static library and makes it part of the program.
Why use C static libraries?
Static libraries allow users to link to programs without having to recompile their code, which saves compilation time.
If you are a programmer and you are using the same function or functions repeatedly. In this case, it is better to put this function or functions in a library to speed up the compilation of the program.
Static libraries are also useful for developers when they want to allow programmers to link to their library, but do not want to give the source code of the library, which is an advantage for the library provider, but obviously not an advantage for the programmer trying to use the library.
How to create them?
Here, I will show you how to create your own static library for your programs.
-Browse for .c files:
Now we are going to convert all .c files to objetc (.o) files at once, you can apply this script at the prompt:
We already have all the object files you want to add to your library. So, to create a library and add those files, you must use this simple script in the directory where all the .o files are:
How to use them?
In order to put our code in a library, we need to organize it as follows:
- One or more .c source files with the code of our functions.
- One or more .h header files with the types (typedefs, structs and enums) and prototypes of the functions we want to be able to use.
As usual, let’s make an example. The files would be these:
It is a file with a couple of simple functions of addition() and subtraction().
An important detail to take into account is the #defines in the header file (.h). When making a library, we do not know in which future programs we are going to use it and how they will be organized. Let’s suppose in a future program that there is a header file file file1.h that #includes ours. Suppose there is also a file2.h that also #includes ours. Finally, with a little more effort, let’s imagine that there is a third file3.c that #includes file1.h and file2.h, i.e., more or less the following:
When we compile file3.c, depending on what is defined in library1.h, we will get an error. The problem is that when you include file1.h, everything in that file is defined, including what is in library1.h. When you include file2.h, you try to define again what is in library1.h, and you get an error that those definitions are defined twice.
La forma de evitar este problema, es poner todas las definiciones dentro de un bloque #ifndef - #endif, con el nombre (_LIBRERIA_1_H en el ejemplo) que nos guste y diferente para cada uno de nuestros archivos de cabecera. Es habitual poner este nombre precedido de _, terminado en _H y que coincida con el nombre del archivo de cabecera, pero en mayúsculas.
Dentro del bloque #ifndef - #endif hacemos una #define de ese nombre (no es necesario darle ningún valor, basta con que esté definido) y luego definimos todos nuestros tipos y prototipos de funciones.
Cuando incluyamos este archivo por primera vez, _LIBRERIA_1_H no estará definido, por lo que irá dentro del bloque #ifndef - #endif y se definirán todos los tipos de funciones y prototipos, incluido el propio _LIBRERIA_1_H. Cuando lo incluyamos por segunda vez, _LIBRERIA_1_H ya estará definido (de la inclusión anterior), por lo que no entrará en el bloque #ifndef - #endif, y nada se redefinirá por segunda vez.
Es un buen hábito hacer esto con todos nuestros .h, sin importar si son para bibliotecas o no. Si miras cualquier .h en el sistema, verás que tienes este tipo de cosas hasta la saciedad. Por ejemplo, en /usr/include/stdio.h, lo primero que aparece después de los comentarios es un #ifndef _STDIO_H.