Le document suivant montre comment créer et utiliser des Dlls sous Linux, il est probable qu'il faille adapter les scripts de compilation sur d'autres versions d'Unix.
L'utilisation des DLLs sous Unix est très semblable à ce qui se fait sous Windows. Sous Unix, l'extension des DLLs est en général .so, et il est courant que le numéro de version soit ajouté derrière l'extension (.so.1, .so.2), un lien symbolique pointant sur la version à utiliser.
Il est possible de lier l'application statiquement ou dynamiquement à la DLL.
Tout comme pour Windows, il faut faire très attention en terme d'interface lorsqu'on décide de la création d'une DLL : Si les prototypes des fonctions ou les structures que l'on passe en argument changent entre 2 versions, cela risque de compromettre le fonctionnement des anciennes applications si cela n'a pas été prévu par le programmeur.
Une solution simple empruntée à Windows peut être de toujours mettre la taille d'une structure en tant que premier membre, et de changer le nom du prototype des fonctions si l'interface change :
// .h (interface de la dll) // Structure version 1 typedef struct MaStructV1 { int cb; // Doit être initialisée par l'application int a; // Quelques membres ... int b; // } MaStructV1; // Structure version 2 typedef struct MaStructV2 { int cb; // Idem int a; int b; // Si l'un des mebre devient obsolète, il faut quand même le conserver int c; // Nouveau mebre } MaStructV2; // Fonction version 1 void maFonction( int a ); // Si le proto change, on change de nom void maFonction2( int a, int b ); // Prototype avec pointeur void monAutreFonction( MaStructV2 * pMaStructV2 ) // .c (code de la dll) void monAutreFonction( MaStructV2 * pMaStructV2 ) { // On determine la version if( pMaStructV2->cb == sizeof(MaStructV1) ) { // C'est une vieille appli V1 qui nous appelle ... } else if( pMaStructV2->cb == sizeof(MaStructV2) ) { // C'est une appli V2 qui nous appelle ... } }
Au niveau du code, il n'y a rien de spécial à faire, c'est dans le makefile que l'on indique que le programme a besoin de la DLL.
Pour que le programme fonctionne, il faut mettre à jour la variable d'environnement LD_LIBRARY_PATH qui contient le chemin des DLLs, et ce, même si la DLL est dans le répertoire courant.
# compilation du programme : La seule difference par rapport # à une compilation classique est que l'on indique le .so # (libshared.so) au lieu du .o hellostat: hellostat.o libshared.so gcc hellostat.o libshared.so -o hellostat # compilation de la dll libshared.so: shared.o gcc -shared -o libshared.so shared.o # on remarque l'option -fpic shared.o: shared.cpp gcc -c -fpic shared.cpp -o shared.o
On utilise l' API dlopen() pour ouvrir la DLL et dlsym() pour aller chercher le pointeur de fonction.
Cette manière de faire est similaire à Windows (utilisation de LoadLibrary() et GetProcAddress()).
// Traitement des erreurs omis pour + de clarete typedef void (*PFHelloShared)(int ); void *module; PFHelloShared pfHelloShared; // ouvre la DLL module = dlopen("./libshared.so", RTLD_LAZY); // Recupere un pointeur sur la fonction pfHelloShared = (PFHelloShared)dlsym(module, "HelloShared"); // Lance la fonction (*pfHelloShared)(8888);
Dans ce cas, pas besoin de mettre à jour LD_LIBRARY_PATH.