Académique Documents
Professionnel Documents
Culture Documents
#include <stdio.h>
int ma_variable=5;
void ma_fonction()
{
printf("Bienvenue dans Ma Fonction !\n");
}
Et voici son fichier d'en-tête toto.h, ne déclarant que les prototypes des fonctions et des variables
globales :
int ma_variable;
void ma_fonction();
int mon_addition(int i,int j);
Remarques :
- le fichier d'en-tête toto.h associé au source toto.c n'est pas généré automatiquement : il faut
l'écrire "à la main"
- - dans la liste des paramètres passés aux fonctions, il faut préciser explicitement le type de
chaque variables, même si plusieurs paramètres sont de même type. Exemple : int i,j ne marche
pas. Il faut écrire int i, int j
Voici le code source titi.c du programme principal. Ce programme invoque le fichier d'en-tête toto.h de
la librairie toto, et fait appel aux fonctions et aux variables globales de cette librairie :
#include <stdio.h>
#include "toto.h"
int main(void)
{
printf("---- Début du programme principal ---- \n");
ma_fonction();
printf("Ma_variable vaut : %i\n",ma_variable);
printf("6+7=%i\n",mon_addition(6,7));
printf("---- Fin du programme principal ---- \n");
return 0;
}
Remarque :
#include "toto.h" indique que le fichier d'en-tête toto.h se trouve dans le répertoire courant (le répertoire
de titi.c). Si on met #include <toto.h>, alors gcc cherchera le fichier d'en-tête toto.h dans le répertoire
/usr/include
Page 1/10
ISET Rades/L2 SEM/Linux embarqué
gcc -c toto.c
Le programme objdump permet de savoir quelles fonctions sont présentes dans le fichier objet toto.o.
Si on tape objdump -t toto.o, on obtient la table des symboles du fichier objet :
SYMBOL TABLE:
00000000 l df *ABS* 00000000 toto.c
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
00000000 l d .rodata 00000000
00000000 l d .note.GNU-stack 00000000
00000000 l d .comment 00000000
00000000 g O .data 00000004 ma_variable
00000000 g F .text 00000018 ma_fonction
00000000 *UND* 00000000 printf
00000018 g F .text 0000001e mon_addition
gcc titi.c
On obtient alors, sans grande surprise, l'erreur suivante de la part de l'éditeur de lien :
Cette erreur indique que le code des fonctions ma_fonction et mon_addition n'ont pas été trouvé par
'éditeur de lien. C'est normal car le code de ces fonctions est dans la librairie toto, et que seul le fichier
d'en-tête de cette librairie a été indiqué dans le programme source : gcc ne connaît donc pas le corps
des fonctions.
Pour indiquer à gcc d'utiliser le fichier objet toto.o lors de l'édition de lien, la ligne de commande est :
Il n'y a alors plus d'erreur de lien, et on obtient un fichier a.out exécutable. Si on lance a.out, on obtient
Le programme titi.c a donc réussit à utiliser les fonctions ma_fonction et mon_addition dont le code est
ans le fichier objet toto.o. Remarque : la déclaration de la variable globale ma_variable est présente
(et suffisante) dans le fichier d'en-tête toto.h.
Page 2/10
ISET Rades/L2 SEM/Linux embarqué
Pour convertir le fichier objet toto.o en une librairie statique libtoto.a, il faut utiliser les 2 lignes de
commande suivantes :
ar cr libtoto.a toto.o
ranlib libtoto.a
On obtient un fichier libtoto.a, dont la table des symboles donnée par objdump -t libtoto.a est :
SYMBOL TABLE :
00000000 l df *ABS* 00000000 toto.c
00000000 l d .text 00000000
00000000 l d .data 00000000
00000000 l d .bss 00000000
Pour compiler titi.c en faisant appel aux fonctions de la librairie statique libtoto.a, il suffit de passer en
paramètre à gcc le nom du fichier de la librairie statique (exactement comme pour un fichier objet) :
Remarque : dans les 2 cas précédents (utilisation d'un fichier objet et utilisation d'une librairie statique),
le code des fonctions ma_fonction et mon_addition provenant initialement de la librairietoto.c a été
introduit dans le fichier exécutable a.out.
Avantage : le fichier a.out n'est plus dépendant des librairies installées dans le système Inconvénient
: si on modifie la librairie toto.c, il faudra alors recompiler titi.c pour obtenir un nouveau programme
exécutable a.out utilisant la nouvelle librairie
SYMBOL TABLE:
000000b4 l d .hash 00000000
000001f0 l d .dynsym 00000000
Page 3/10
ISET Rades/L2 SEM/Linux embarqué
Page 4/10
ISET Rades/L2 SEM/Linux embarqué
Pour compiler titi.c en utilisant la librairie dynamique libtoto.so il faut indiquer à gcc 2 informations :
1 - quelle librairie dynamique l'éditeur de lien doit-il utiliser : paramètre –l
2 - dans quel répertoire se trouve le fichier .so de la librairie dynamique : paramètre –L
La compilation de titi.c en utilisant la librairie dynamique toto se fait alors avec la ligne de commande
suivante :
Si le paramètre -L n'est pas passé à gcc, l'éditeur de lien recherche alors les fichiers .so de librairie
dynamiques dans le répertoire /usr/lib
gcc toto.o -> édition de lien seulement (utilisation du linkeur LD) -> on
obtient un exécutable a.out
Pour obtenir un exécutable, il faut une et une seule fonction main dans l'ensemble des sources et des
librairies. Si un programme fait appel à des fonctions extérieures qui ne sont pas définit dans son code
source, il faut l'indiquer à gcc sur la ligne de commande. Exemple : le programme titi.c faut appel à
des fonctions contenues dans toto.c. Il y a alors 4 manières de compiler titi.c :
Ces 4 lignes de commande génèrent un exécutable a.out dont le point d'entrée est la fonction main()
de titi.c. Enfin, le programme objdump permet d'aller voir les symboles présents dans :
- un fichier objet
- une librairie statique
- une librairie dynamique
- un fichier exécutable ELF32 (a.out)
Page 5/10
ISET Rades/L2 SEM/Linux embarqué
Exemple : si le programme a.out a été compilé en utilisant la bibliothèque partagée libtoto.so, alors la
commande ltrace a.out renvoie :
On voit bien à travers cette dernière commande que le programme a.out fait appel à la librairie
partagée libtoto.so.
Page 6/10
ISET Rades/L2 SEM/Linux embarqué
On constate que la librairie libjpeg.so est installée dans le système. Où se trouve le fichier de librairie
dynamique libjpeg.so ?
whereis libjepg.so
Quelles fonctions contient cette librairie libjpeg.so ? Pour cela, affichons sa table de symboles grâce à
objdump :
objdump -T /usr/lib/libjpeg.so
Parmi tous les résultats affichés, les fonctions de la librairies sont précédées du mot Base. Filtrons la
sortie de objdump grâce à grep afin d'affiner le résultat :
On obtient alors la liste des 110 fonctions disponibles dans la librairie dynamique libjpeg.so :
Page 7/10
ISET Rades/L2 SEM/Linux embarqué
Page 8/10
ISET Rades/L2 SEM/Linux embarqué
Parmi toutes ces fonctions on trouve la fonction jpeg_read_header (en gras ci-dessus) qui permet de
lire l'en-tête d'un fichier JPEG, afin de connaître, par exemple, la résolution en pixels de l'image. Avant
d'utiliser cette fonction pour afficher la résolution d'une image JPEG, il nous faut trouver dans le système
le fichier d'en-tête (avec l'extension .h) relatif à cette librairie partagée libjpeg.so.
ls /usr/include/*jpeg*.h
ATTENTION : le fichier de libraire partagée s'appelle libjpeg.so mais le fichier d'en-tête s'appelle
jpeglib.h
Pour utiliser les fonctions et les types de la librairie libjpeg.so il suffit de rajouter #include <jpeglib.h>
au début du programme.
int main(void)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE *file;
char *fichier="toto.jpg";
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
if ((file=fopen(fichier,"rb"))==NULL)
{
fprintf(stderr,"Erreur : impossible d'ouvrir le fichier texture.jpgn");
exit(1);
}
Page 9/10
ISET Rades/L2 SEM/Linux embarqué
jpeg_stdio_src(&cinfo, file);
jpeg_read_header(&cinfo, TRUE);
printf("La largeur de l'image est %i pixels\n",cinfo.image_width);
printf("La hauteur de l'image est %i pixels\n",cinfo.image_height);
return (0);
}
Pour le compiler on utilisera la ligne de commande suivante (l'éditeur de lien fait appel à la librairie
libjpeg.so) :
Où trouver de l’aide
Les fichiers d’aides (.doc) des différentes librairies installées dans le système se trouvent dans le
répertoire /usr/share/doc.
Le programme h2xs permet de convertir un fichier d'en-tête .h en un module Perl .pm afin qu'un
programme Perl puisse utiliser une librairie partagée écrite en C. Utilisons la librairie toto.c et son fichier
d'entête décrits ci-dessus :
h2xs toto.h
Page 10/10