# création et utilisation des librairies en langage de programmation C

description : comment créer et utiliser des librairies en langage C sur GNU/Linux
categories : Coding;
tags : C; Linux;

Création et utilisation des librairies en langage de programmation C

Qu'est ce qu'une librairie ?

En langage de programmation C, une librairie est un fichier contenant du code compilé pouvant être utilisé à souhait par un programme. Ce qui permet de faciliter la tache de programmation et de rendre le programme modulaire.

Il existe trois types de librairies en langage C :

  • les librairies statiques
  • les librairies partagées
  • les librairies chargées dynamiquement

Les librairies statiques

Ce sont des librairies installées dans un programme avant que ce programme puisse être exécuté. Elles sont donc installées dans ce programme au moment de la compilation. Ces librairies sont également connues sous le nom d'archives. Leur nom contient le suffixe ".a" sur GNU/Linux et ".lib" sur Microsoft Windows.

Création d'une librairie statique sur GNU/Linux

Le fichier lib_foobar.h de la lib :

1
2
3
4
5
6
#ifndef _LIB_FOOBAR_H_
#define _LIB_FOOBAR_H_

void foobar(void);

#endif

Le fichier lib_foobar.c de la lib :

1
2
3
4
5
6
7
#include <stdio.h>
#include "lib_foobar.h"

void foobar(void)
{
    printf("foobar() depuis la lib statique\n");
}

Je compile la lib :

1
2
gcc -c lib_foobar.c
ar rcs lib_foobar.a lib_foobar.o

Le fichier main.c du programme utilisant la lib :

1
2
3
4
5
6
#include "lib_foobar.h"

void main()
{
    foobar();
}

Je compile le programme :

gcc prog.c lib_foobar.a -o prog

Puis, je l'exécute :

1
2
$ ./prog 
foobar() depuis la lib statique

Les librairies partagées

Ce sont les librairies qui sont chargées par un programme lorsque celui-ci démarre. Leur nom contient le suffixe ".so" sur GNU/Linux et ".dll" sur Microsoft Windows.

Création d'une librairie partagée sur GNU/Linux

Le fichier lib_foobar.h de la lib :

1
2
3
4
5
6
#ifndef _LIB_FOOBAR_H_
#define _LIB_FOOBAR_H_

void foobar(void);

#endif

Le fichier lib_foobar.c de la lib :

1
2
3
4
5
6
7
#include <stdio.h>
#include "lib_foobar.h"

void foobar(void)
{
    printf("foobar() depuis la lib partagée\n");
}

Je compile la lib :

gcc -fPIC -shared lib_foobar.c -o lib_foobar.so

Le fichier main.c du programme utilisant la lib partagée :

1
2
3
4
5
6
#include "lib_foobar.h"

void main()
{
    foobar();
}

Je compile le programme :

gcc main.c lib_foobar.so -o prog

Ou de cette façon :

gcc prog.c -L. -l_foobar -o prog

Puis, je l'exécute en spécifiant le dossier où ce trouve la lib grace a la variable d'environnement LD_LIBRARY_PATH :

1
2
$ LD_LIBRARY_PATH="." ./prog
foobar() depuis la lib partagée

Les librairies chargées dynamiquement

Ce sont les librairies partagées qui sont chargées par un programme lorsque celui-ci le décide et non lors de son démarage. Pour chargée une librairie partagée il faut utiliser la fonction dlopen dont voici le prototype :

void *dlopen(const char *filename, int flags);

Pour pouvoir exécuter une fonction de la librairie partagée nouvellement chargée, il faut utiliser la fonction dlsym dont voici le prototype :

void *dlsym(void *handle, const char *symbol);

La fonction permettant d'obtenir la raison d'une eventuelle erreurs se nomme dlerror et voici son prototype :

char *dlerror(void);

Puis, pour décharger la librairie, il existe la fonction dlclose dont voici le prototype :

int dlclose(void *handle);

Voici maintenant le fichier .c du programme utilisant la lib partagée lib_foobar.so chargée dynamiquement :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <dlfcn.h>
#include "lib_foobar.h"

int main()
{
    void *lib_handle;
    void (*fn)(void);

    lib_handle = dlopen("./lib_foobar.so", RTLD_LAZY);

    if (lib_handle == NULL)
    {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    fn = dlsym(lib_handle, "foobar");

    if (fn == NULL)
    {
        fprintf(stderr, "%s\n", dlerror());
        return 1;
    }

    (*fn)();

    dlclose(lib_handle);

    return 0;
}

Je compile le programme :

gcc main.c -ldl

Puis, je l'exécute :

1
2
$ ./a.out 
foobar() depuis la lib partagée

Fin

Exemple de programme utilisant des librairies partagées : http://syndrome.sagwin.org/ : Un bot IRC modulable écrit par Thaeron.

Happy coding !