Provided by:
manpages-fr_1.67.0-1_all 
NOM
dladdr, dlclose, dlerror, dlopen, dlsym, dlvsym - Interface de
programmation pour le chargeur de bibliothèques dynamiques.
SYNOPSIS
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
char *dlerror(void);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
DESCRIPTION
Les quatres fonctions dlopen(), dlsym(), dlclose(), dlerror()
implémentent l’interface pour le chargeur de bibliothèques dynamiques.
dlerror
La fonction dlerror() renvoie une chaîne de caractères, compréhensible
par l’homme, décrivant la dernière erreur survenue dans n’importe
laquelle des routines « dl » (dlopen, dlsym ou dlclose) depuis le
dernier appel à dlerror(). Elle renvoie NULL si aucune erreur n’est
survenue depuis l’initialisation ou depuis son dernier appel.
dlopen
La fonction dlopen() charge la bibliothèque dynamique depuis le fichier
dont le nom est fourni dans la chaîne filename (terminée par un
caractère nul) et renvoie un descripteur opaque (handle) représentant
la bibliothèque dynamique. Si l’argument filename est un pointeur
NULL, le descripteur renvoyé correspond au programme principal. Si
filename contient une barre oblique (« / »), il est interprété comme un
chemin (relatif ou absolu). Autrement, le chargeur dynamique cherche
la bibliothèque de la façon suivante (voir ld.so(8) pour plus de
détails) :
o (ELF seulement) si le fichier exécutable pour le programme
appelant contient la balise DT_RPATH mais pas la balise
DT_RUNPATH, les répertoires listés dans la balise DT_RPATH
seront parcourus.
o Si la variable d’environnement LD_LIBRARY_PATH est définie et
contient une liste de répertoires (séparés par des deux-points
« : »), ces répertoires seront parcourus. (Par mesure de
sécurité, cette variable est ignorée dans le cas de programmes
set-UID et set-GID.)
o (ELF seulement) si le fichier exécutable pour le programme
appelant contient la balise DT_RUNPATH, les répertoires listés
dans cette balise seront parcourus.
o Le fichier cache /etc/ld.so.cache (maintenu par ldconfig(8)) est
vérifié pour voir s’il contient une entrée correspondant à
filename.
o Les répertoires /lib et /usr/lib sont parcourus (dans cet
ordre).
Si la bibliothèque a des dépendances sur d’autres bibliothèques
partagées, celles-ci seront automatiquement chargées par le chargeur
dynamique, en utilisant les mêmes règles. (Le processus peut être
récursif si ces bibliothèques ont, à leur tour, des dépendances, et
ainsi de suite.)
La valeur de flag peut être soit RTLD_LAZY, soit RTLD_NOW. Lorsque
RTLD_NOW est spécifiée, ou que la variable d’environnement LD_BIND_NOW
est positionnée avec une chaîne non vide, tous les symboles non définis
sont résolus avant le retour de dlopen(). Si cela ne peut pas être
fait, une erreur est renvoyée. Autrement, la liaison est fainéante :
les symboles sont résolus la première fois lorsqu’on en a besoin.
En option, on peut ajouter (avec un OU binaire) l’attribut RTLD_GLOBAL
rendant les symboles externes de la bibliothèque disponibles pour les
bibliothèques chargées ultérieurement. (Le contraire de RTLD_GLOBAL est
RTLD_LOCAL. C’est la valeur par défaut.)
Si l’argument filename est un pointeur NULL, le descripteur renvoyé
correspond au programme principal. Lorsqu’il est passé à dlsym(), ce
descripteur provoque la recherche d’un symbole dans le programme
principal, puis dans toutes les bibliothèques partagées chargées au
démarrage du programme, puis dans toutes les bibliothèques partagées
chargées par dlopen() avec l’attribut RTLD_GLOBAL.
Les références externes de la bibliothèque sont résolues en utilisant
les bibliothèques mentionnées dans sa liste de dépendances, et toutes
les autres bibliothèques éventuellement ouvertes auparavant avec
l’attribut RTLD_GLOBAL. Si l’édition des liens de l’exécutable a été
faite avec l’option « -rdynamic » (ou, de manière synonyme,
« --export-dynamic »), alors ses symboles globaux seront également
employés pour résoudre les références de la bibliothèque chargée
dynamiquement.
Si la même bibliothèque est chargée une nouvelle fois avec dlopen(), le
même descripteur sera renvoyé. Un compte du nombre de chargements est
toutefois conservé afin d’éviter de la décharger avant que la fonction
dlclose() n’ait été appelée autant de fois que dlopen() a réussi. La
routine _init, si elle existe, est appelée une seule fois. Mais un
appel postérieur avec RTLD_NOW peut forcer la résolution de symboles
pour une bibliothèque précédemment chargée avec RTLD_LAZY.
Si dlopen() échoue pour une raison quelconque, elle renvoie NULL.
dlsym
La fonction dlsym() prend un descripteur de bibliothèque dynamique
renvoyée par dlopen() et un nom de symbole terminé par un caractère
nul, et renvoie l’adresse où ce symbole a été chargé. Si le symbole
n’est pas trouvé, soit dans la bibliothèque spécifiée, soit dans
n’importe quelle bibliothèque chargée automatiquement par dlopen()
lorsque cette bibliothèque a été chargée, dlsym() renvoie NULL. (La
recherche effectuée par dlsym() est en largeur d’abord à travers
l’arbre des dépendances de ces bibliothèques.) Le symbole pouvant
légitimement avoir la valeur NULL (la valeur NULL renvoyée par dlsym()
n’indique pas nécessairement une erreur), la bonne manière de vérifier
si une erreur s’est produite est d’appeler dlerror() pour effacer toute
ancienne condition d’erreur, puis d’appeler dlsym() et appeler une
nouvelle fois dlerror() en sauvegardant sa valeur de retour dans une
variable et vérifier si la valeur sauvegardée n’est pas NULL.
Il y a deux pseudo-descripteurs spéciaux : RTLD_DEFAULT et RTLD_NEXT.
Le premier recherche la première occurrence du symbole désiré en
utilisant l’ordre de recherche des bibliothèques par défaut. Le second
recherche l’occurrence suivante d’une fonction à partir de la
bibliothèque en cours. Ceci permet de fournir un encadrement pour une
fonction se trouvant dans une autre bibliothèque partagée.
dlclose
La fonction dlclose() décrémente le nombre de références sur la
bibliothèque dynamique dont le descripteur est handle. Si ce nombre
descend à zéro et si aucune autre bibliothèque n’emploie des symboles
exportés par celle-ci, elle est déchargée.
La fonction dlclose() renvoie 0 si elle réussit, et une valeur non
nulle si une erreur est survenue.
Les symboles obsolètes _init et _fini
L’éditeur de liens reconnait les symboles spéciaux _init et _fini. Si
une bibliothèque dynamique exporte une routine nommée _init, son code
est exécuté après le chargement, avant le retour de dlopen(). Si la
bibliothèque exporte une routine nommée _fini, elle est appelée juste
avant le déchargement. Au cas où vous voudriez éviter le lien avec les
fichiers de démarrage du système, vous pouvez préciser le paramètre
« -nostartfiles » sur la ligne de commande de gcc.
L’utilisation de ces routines ou des options gcc -nostartupfiles ou
-nostdlib n’est pas recommandée. Il peut en résulter un comportement
non désiré tant que les routines constructeur/destructeur ne sont pas
exécutées (à moins que des mesures spéciales ne soient prises).
À la place, les bibliothèques devraient exporter les routines en
utilisant les fonctions attributs __attribute__((constructor)) et
__attribute__((destructor)). Voir les pages info de gcc pour plus
d’information sur celles-ci. Les routines constructeur sont exécutées
avant que dlopen revienne et les routines destructeur sont exécutées
avant que dlclose revienne.
EXTENSIONS GNU
La GlibC a ajouté deux fonctions, qui ne sont pas décrites par POSIX,
dont les prototypes sont :
#define GNU_SOURCE
#include <dlfcn.h>
int dladdr(void *addr, Dl_info *info);
void *dlvsym(void *handle, char *symbol, char *version);
La fonction dladdr() prend un pointeur vers une fonction et essaie de
résoudre le nom et le fichier où elle se trouve. L’information est
stockée dans une structure Dl_info :
typedef struct {
const char *dli_fname;/* File name of defining object */
void *dli_fbase; /* Load address of that object */
const char *dli_sname;/* Name of nearest lower symbol */
void *dli_saddr; /* Exact value of nearest symbol */
} Dl_info;
dladdr() renvoie 0 en cas d’erreur et une valeur non nulle si elle
réussit.
La fonction dlvsym() effectue la même chose que dlsym() mais prend une
chaîne version comme argument supplémentaire.
EXEMPLE
Charger la bibliothèque mathématique et afficher le cosinus de 2.0 :
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("libm.so", RTLD_LAZY);
if (!handle) {
fprintf (stderr, "%s\n", dlerror());
exit(1);
}
dlerror(); /* Clear any existing error */
*(void **) (&cosine) = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fprintf (stderr, "%s\n", error);
exit(1);
}
printf ("%f\n", (*cosine)(2.0));
dlclose(handle);
return 0;
}
Supposons que le programme s’appelle « foo.c », on doit le compiler
ainsi :
gcc -rdynamic -o foo foo.c -ldl
Une bibliothèque (disons bar.c) qui exporte _init() et _fini() sera
compilée comme suit :
gcc -shared -nostartfiles -o bar bar.c
NOTES
Les symboles RTLD_DEFAULT et RTLD_NEXT sont définis dans <dlfcn.h>
seulement si _GNU_SOURCE a été définie avant l’inclusion.
HISTORIQUE
L’interface standard dlopen provient de SunOS. Ce système a également
dladdr mais pas dlvsym.
CONFORMITÉ
POSIX 1003.1-2003 describes dlclose, dlerror, dlopen, dlsym.
VOIR AUSSI
ld(1), ldd(1), ld.so(8), ldconfig(8), ld.so info pages, gcc info pages,
ld info pages
TRADUCTION
Christophe Blaess, 2000-2003.
Alain Portal, 2005