next up previous contents Next: Les projets en C Up: Eléments de programmation C. Previous:  strace.   Table des matières  


23.3 Bibliothèques du C.

Nous avons déjà mentionné la bibliothèque standard du C. Le langage C en soi ne fait pas grand-chose; tout ce qui est utile se trouve dans des fonctions externes. Celles-ci sont groupées en bibliothèques. La bibliothèque standard du C est le fichier /lib/libc.so.6. Pour afficher toutes les fonctions de cette bibliothèque, lancez:

nm /lib/libc.so.6 
nm /lib/libc.so.6 | grep ' T ' | cut -f3 -d' ' | grep -v '^_' | sort -u \ 
| less


De nombreuses fonctions ont une page de man mais, certaines ne présentent pas de documentation si bien qu'il est nécessaire de lire les explications fournies dans les fichiers d'en-têtes. Il vaut mieux ne pas utiliser de fonctions qui ne seraient pas standards (c'est-à-dire qui ne sont pas usuelles sur d'autres systèmes).

La création de sa propre bibliothèque est simple. Supposons que nous ayons deux fichiers contenant plusieurs fonctions que nous souhaitons compiler pour les placer dans une bibliothèque. Les fichiers s'appellent simple_math_sqrt.c et simple_math_pow.c:

#include <stdlib.h> 
#include <stdio.h> 
 
static int abs_error (int a, int b) 
{ 
   if (a < b) { 
      return a - b; 
   return b - a; 
} 
 
int simple_math_isqrt (int x) 
{ 
   int result; 
   if (x < 0) { 
       fprintf (stderr, 
       "simple_math_sqrt: taking the sqrt of a negative number\n"); 
      abort (); 
   } 
    result = 2; 
    while (abs_error (result * result, x) > 1) { 
       result = (x / result + result) / 2; 
    } 
    return result; 
} 

Et pour simple_math_pow.c, nous avons:

#include <stdlib.h> 
#include <stdio.h> 
 
int simple_math_ipow (int x, int y) 
{ 
   int result; 
   if (x == 1 || y == 0)

      return 1; 
   if (x == 0 && y < 0) { 
      fprint (stderr, 
       "simple_math_pow: raising zero to a negative 
           power\n"); 
      abort (); 
   } 
   if (y < 0) 
      return 0; 
   result = 1; 
   while (y > 0) { 
      result = result * x; 
      y = y - 1; 
   } 
   return result; 
} 



Nous allons appeler notre bibliothèque simple_math. Il sera judicieux de nommer toutes les fonctions qu'elle regroupera sous la terminologie simple_math.??????. La fonction abs_error ne sera pas utilisée hors du fichier simple_math/sqrt.c et, par conséquent, nous plaçons le terme static devant sa déclaration, ce qui signifie qu'il s'agit d'une fonction locale.

Nous pouvons à présent compiler le code de cette manière:

gcc -Wall -c simple_math_sqrt.c 
gcc -Wall -c simple_math_pow.c 


L'option -c vaut pour compile only (compiler seulement). Le code ne sera pas converti en exécutable. Les fichiers produits seront caractérisés par une extension .o. On les appelle des fichiers objets.

Maintenant, il faut archiver ces fichiers dans la bibliothèque. A cette fin, on fait usage de la commande ar (précurseur de tar):

ar r libsimple_math.a simple_math.sqrt.o simple_math_pow.o 
ranlib libsimple_math.a 


Remarquons que le nom de la bibliothèque est précédé de ``lib'' et que la commande ranlib permet d'indicer l'archive.

La bibliothèque est maintenant utilisable. Créons un fichier appelé mon_test.c:

#include <stdlib.h> 
#include <stdio.h> 
int main (int argc, char *argv[]) 
{ 
    printf ("%d\n", simple_math_ipow (4, 3)); 
    printf ("%d\n", simple_math_isqrt (50)); 
    return 0; 
} 


et exécutez:

gcc -Wall -c mon_test.c 
gcc -L. -o mon_test mon_test.o -l simple_math 


La première commande compile le fichier mon_test.c en mon_test.o. Ensuite, on procède à l'étape d'édition de liens qui combine mon_test.o et les bibliothèques pour produire un exécutable unique. L'option L. signifie qu'il faut regarder dans le répertoire courant pour toute bibliothèque. L'option -lsimple_math signifie qu'il faut prendre en compte la bibliothèque libsimple_math.a (lib et .a sont ajoutés automatiquement). Cette opération d'édition de liens est statique [cela n'a rien à voir avec le mot-clé static utilisé dans le programme simple_math_sqrt.c]parce qu'elle a lieu avant que le programme ne soit lancé et qu'elle inclut tous les fichiers objets dans un exécutable.

Notons encore qu'il arrive souvent que de nombreuses bibliothèques statiques soient liées à un même programme. Ici, l'ordre est important: la bibliothèque ayant le moins de dépendances devra être citée en dernier ou alors, vous obtiendrez des erreurs de référencement de symboles (symbol referencing errors).

Nous pouvons aussi créer un fichier d'en-tête simple_math.h pour tirer parti de la bibliothèque:

/* calculates the integer square root, aborts on error */ 
int simple_math_isqrt (int x); 
 
/* calculates the integer power, aborts on error */ 
int simple_math_ipow (int x, int y);  


Ajoutez la ligne #include "simple_math.h" au début du fichier mon_test.c:

#include <stdlib.h> 
#include <stdio.h> 
#include "simple_math.h" 


Cette formulation permet de se débarrasser des messages d'alerte associés à la déclaration implicite de fonction (implicit declaration of function). D'habitude, on utilise une forme du type #include <simple_math.h>, mais en l'occurrence, il s'agit d'un fichier d'en-tête d'un répertoire courant (notre propre fichier d'en-tête) et, c'est le cas précisément où il faut utiliser ``simple_math.h'' au lieu de <simple_math.h>.


next up previous contents Next: Les projets en C Up: Eléments de programmation C. Previous:  strace.   Table des matières  
1-01-2006