Les bibliothèques
Les bibliothèques (libraries) permettent de modulariser le code, de fournir des fonctionnalités et de réduire le temps de compilation et/ou la taille de l'exécutable. Il en existe trois sortes en C++ :
Bibliothèques header-only
Ce format est populaire grâce à sa simplicité d'utilisation : il suffit d'inclure un unique fichier pour disposer du code. Aucun problème d'ABI (Application Binary Interface) ou de portabilité (différents OS, compilateurs et machines) n'apparaît puisque le code est recompilé lorsqu'il est inclut, avec les options du compilateur de l'utilisateur.
Parfois, ces librairies incluent un second fichier, le fichier source de la librairie. Il peut être contenu dans le premier fichier : il suffit alors de définir une macro pour que le fichier source soit défini.
Cependant, ces librairies vont augmenter le temps de compilation, et nécessitent de mettre le code source à disposition.
Bibliothèques statiques
Une bibliothèque statique est similaire à un aggrégat d'Object Files. Elle est compilée séparément du code de l'utilisateur de la bibliothèque : il faut donc qu'elle soit compatible. Pour cela, un système de build avec le code source et/ou des distributions de la bibliothèque (debug/release, linux/windows, 32/64bits, ...) sont mis à disposition.
Les outils ar (pour Linux) et lib (pour Windows, utilisé par défaut) permettent de créer des bibliothèques statiques incorporant d'autres bibliothèques statiques.
De la même façon que les Object Files, la bibliothèque est ajoutée à l'exécutable lors du linker. Elle peut donc bénéficier des Link-Time Optimisation (même si les librairies et l'exécutable ne sont pas écrits dans le même langage).
Bibliothèques dynamiques
Les bibliothèques dynamiques sont similaires à des exécutables qui ne disposent pas du point d'entrée main mais de plusieurs autres points d'entrée (les fonctions mises à disposition). Pour cela, des modificateurs de visibilité sont utilisés (propres au compilateur).
Par rapport aux bibliothèques statiques, les bibliothèques dynamiques sont moins performantes, car elles sont chargées a l'exécution du programme (les Link-Time Optimisation sont impossibles). Elles doivent rester disponibles lors de l'utilisation de l'exécutable, car elles ne sont pas intégrées à l'intérieur (ce qui diminue sa taille) : cela permet à plusieurs exécutables d'utiliser la même bibliothèque dynamique. Tant que son ABI est stable, la bibliothèque dynamique peut être changée sans toucher à l'exécutable.
Attention au phénomène de DLL Hell (terme apparu pour certains programmes sur Windows), qui arrive lorsqu'il y a trop de dépendances entre les bibliothèques dynamiques utilisées.
Chargement dynamique
Les bibliothèques dynamiques peuvent être chargées manuellement, pendant que l'exécutable est lancé. Cela peut être utile par exemple pour utiliser des plugins depuis le programme.
Pour cela, les fonctions dlopen
et dlclose
(Linux) ou LoadLibrary
et FreeLibrary
(Windows) permettent de charger et libérer une bibliothèque dynamique. Ensuite, ses symboles peuvent être accédés avec dlsym
ou GetProcAddress
.
Si ces fonctions retournent un pointeur nul, elles ont échoué. Leur erreur peut être lue avec dlerror
(sur Linux) ou GetLastError
(sur Windows).
Pour aller plus loin
Afin d'utiliser la bibliothèque dans d'autres langages, les fonctions en C++ doivent généralement être exportées avec la convention du C : cela se fait avec extern "C".
La compabilité entre les librairies et les exécutables est importante, il faut donc faire attention à la stabilité de l'ABI proposée.
Les symboles des bibliothèques dynamiques peuvent être renommés avec objcopy
(sur Linux). Il faut alors également modifier son header.
Last updated