C / C++ Comment Fonctionne La Liaison Dynamique Sur Différentes Plates-Formes?

Comment fonctionne la liaison dynamique en général?

Sous Windows (LoadLibrary), vous avez besoin d'un .dll à appeler au moment de l'exécution, mais au moment du lien, vous devez fournir un correspondant .fichier lib ou le programme ne sera pas lié... Ce qui ne l' .le fichier lib contient? Une description de la .méthodes dll? N'est-ce pas ce que les en-têtes contiennent?

Par ailleurs, sur *nix, vous n'avez pas besoin d'un fichier lib... Comment comment le compilateur sait - il que les méthodes décrites dans l'en-tête seront disponibles à l'exécution?

Comme un débutant, quand vous pensez à l'un des deux régimes, alors l'autre, aucun d'entre eux n'a de sens...

24
demandé sur Charlie 2014-04-04 14:44:22

9 réponses

Pour répondre À vos questions une par une:

  • La liaison Dynamique reporte une partie du processus de liaison à l'exécution. Il peut être utilisé de deux façons: implicitement et explicitement. Implicitement, l'éditeur de liens statique insérera des informations dans le exécutable qui entraînera le chargement et la résolution de la bibliothèque symboles nécessaires. Explicitement, vous devez appeler LoadLibrary ou dlopen manuellement, puis GetProcAddress/dlsym pour chaque symbole que vous devez utiliser. Le chargement implicite est utilisé pour les choses comme le système bibliothèque, où la mise en œuvre dépendra de la version du système, mais l'interface est garanti. Le chargement explicite est utilisé pour des choses comme des plugins, où l' bibliothèque à charger sera déterminé au moment de l'exécution.

  • Le fichier .lib n'est nécessaire que pour le chargement implicite. Il contient les informations que la bibliothèque fournit réellement ceci symbole, de sorte que l'éditeur de liens ne se plaindra pas que le symbole est indéfini, et il indique à l'éditeur de liens dans quelle bibliothèque de symboles être situé, de sorte qu'il peut insérer les informations nécessaires pour provoquer cette bibliothèque à charger automatiquement. Tous les fichiers d'en-tête dire au compilateur est que les symboles existeront, quelque part; le linker a besoin du .lib pour savoir où.

  • Sous Unix, toutes les informations sont extraites de la .so. Pourquoi Windows nécessite deux fichiers distincts, plutôt que mettre toutes les informations dans un seul fichier, je ne sais pas; c'est en fait dupliquer la plupart des informations, puisque le les informations nécessaires dans le .lib sont également nécessaires dans le .dll. (Peut-être des questions de licences. Vous pouvez distribuer votre programme avec le .dll, mais personne ne peut lier contre les bibliothèques à moins que ils ont un .lib.)

La principale chose à retenir est que si vous voulez un chargement implicite, vous devez fournir à l'éditeur de liens les informations appropriées, soit avec un fichier .lib ou un fichier .so, afin qu'il puisse insérer informations dans l'exécutable. Et ça si tu veux explicite chargement, vous ne pouvez pas vous référer à l'un des symboles de la bibliothèque directement; vous devez appeler GetProcAddress/dlsym pour obtenir leur s'adresse à vous-même (et faites un casting drôle pour les utiliser).

21
répondu James Kanze 2014-04-04 11:26:34

Le fichier .lib sur Windows n'est pas nécessaire pour charger une bibliothèque dynamique, il offre simplement un moyen pratique de le faire.

En principe, vous pouvez utiliser LoadLibrary pour charger la dll, puis utiliser GetProcAddress pour accéder aux fonctions fournies par cette dll. La compilation du programme englobant n'a pas besoin d'accéder à la dll dans ce cas, elle n'est nécessaire qu'au moment de l'exécution (ie. quand LoadLibrary s'exécute réellement). MSDN a un exemple de code .

L'inconvénient ici est que vous devez écrire manuellement du code pour charger les fonctions de la dll. Dans le cas où vous avez compilé la dll vous-même en premier lieu, ce code duplique simplement la connaissance que le compilateur aurait pu extraire du code source dll automatiquement (comme les noms et les signatures des fonctions exportées).

C'est ce que fait le fichier .lib: Il contient les appels GetProcAddress pour les fonctions exportées par les DLL, générées par le compilateur afin que vous n'ayez pas à vous en soucier. En termes de Windows, c'est appelé liaison dynamique en temps de chargement, puisque la Dll est chargée automatiquement par le code de la .fichier lib lorsque votre programme englobant est chargé (par opposition à l'approche manuelle, appelée run-time dynamic linking).

13
répondu ComicSansMS 2014-04-04 11:11:27

Comment fonctionne la liaison dynamique en général?

Le fichier dynamic link library (aka shared object) contient des instructions et des données de code machine, ainsi qu'une table de métadonnées indiquant quels décalages dans ce code / données se rapportent à quels "symboles" , le type de symbole (par exemple fonction vs données), le nombre d'octets ou de mots dans les données, et quelques autres choses. Différents systèmes d'exploitation auront tendance à avoir différents formats de fichiers objets partagés, et en effet le même système d'exploitation peut en supporter plusieurs, mais c'est l'essentiel.

Alors, imaginez la bibliothèque partagée est un gros morceau d'octets avec un indice comme ceci:

SYMBOL       ADDRESS        TYPE        SIZE
my_function  1000           function    2893
my_number    4800           variable    4

En général, le type exact des symboles n'a pas besoin d'être capturé dans la table de métadonnées - il est prévu que les déclarations dans les fichiers d'en-tête de la bibliothèque contiennent toutes les informations manquantes. C++ est un peu spécial-par rapport à dire C-parce que la surcharge peut signifier qu'il y a plusieurs fonctions avec le même nom, et les espaces de noms permettent d'autres symboles qui sinon, être nommé de manière ambiguë-pour cette raison, name mangling est généralement utilisé pour concaténer une représentation de l'espace de noms et des arguments de fonction au nom de la fonction, formant quelque chose qui peut être unique dans le fichier objet de la bibliothèque.

UN programme voulant utiliser l'objet partagé peut généralement faire l'une des deux choses suivantes:

  • Demandez au système d'exploitation de charger lui-même et l'objet partagé à peu près au même moment (avant d'exécuter main()), avec le chargeur du système d'exploitation responsable pour trouver les symboles et examiner les métadonnées dans l'image du fichier de programme sur l'utilisation de ces symboles, puis patcher les adresses de symboles dans la mémoire que le programme utilise, de sorte que le programme peut alors fonctionner et fonctionner fonctionnellement comme s'il avait connu les adresses de symboles quand il a été compilé (mais peut-être un peu]}

  • Ou, explicitement dans son propre appel de code source dlopen quelque temps après main s'exécute, puis utilisez dlsym ou similaire pour obtenir les adresses de symboles, enregistrez - les dans (fonction/données) des pointeurs basés sur la connaissance du programmeur des types de données attendus, puis appelez-les explicitement en utilisant les pointeurs.

Sous Windows (LoadLibrary), vous avez besoin d'un .dll à appeler au moment de l'exécution, mais au moment du lien, vous devez fournir un correspondant .fichier lib ou le programme ne sera pas lié...

Ça ne sonne pas bien. Devrait être l'un ou l'autre je pense.

WTF fait le .le fichier lib contient? Une description de la .méthodes dll? N'est-ce pas ce que les en-têtes contiennent?

Un fichier lib est - à ce niveau de description - à peu près le même qu'un fichier objet partagé... la principale différence est que le compilateur trouve les adresses de symboles avant que le programme ne soit expédié et exécuté.

8
répondu Tony Delroy 2014-04-04 12:01:15

Les systèmes modernes * nix dérivent le processus de liaison dynamique à partir du système D'exploitation Solaris. Linux, en particulier, n'a pas besoin de séparer .fichier lib car toutes les dépendances externes sont contenues au format ELF. .interp la section du fichier ELF indique qu'il y a des symboles externes à l'intérieur de cet exécutable qui devaient être résolus dynamiquement. Cela vient de liaison dynamique.

, Il existe un moyen de gérer la liaison dynamique dans l'espace utilisateur. Cette méthode est appelée chargement dynamique. C'est quand vous utilisez des appels système pour obtenir des pointeurs de fonction vers des méthodes externes *. so.

Plus d'informations peuvent être trouvées à partir de cet article http://www.ibm.com/developerworks/library/l-dynamic-libraries/.

2
répondu mesmerizingr 2014-04-04 11:12:01

Relatedly, sur OS X (et je suppose *nix... dlopen), vous n'avez pas besoin d'un fichier lib... Comment comment le compilateur sait - il que les méthodes décrites dans l'en-tête seront disponibles à l'exécution?

Les compilateurs ou les lieurs n'ont pas besoin de telles informations. Vous, le programmeur, devez gérer la situation où les bibliothèques partagées que vous essayez d'ouvrir par dlopen() peuvent ne pas exister.

2
répondu Lee Duhem 2014-04-05 08:34:43

Vous pouvez utiliser un fichier DLL dans Windows de deux façons: soit vous liez avec lui, et vous avez terminé, rien de plus à faire. ou vous le chargez dynamiquement pendant l'exécution.

Si vous le liez, le fichier de bibliothèque DLL est utilisé. La bibliothèque de liens contient des informations que l'éditeur de liens utilise pour savoir quelle DLL charger et où se trouvent les fonctions DLL, afin qu'il puisse les appeler. Lorsque votre programme est chargé, le système d'exploitation charge également la DLL pour vous, essentiellement ce qu'il appelle LoadLibrary pour vous.

Dans d'autres systèmes d'exploitation (comme OS X et Linux), il fonctionne de manière similaire. La différence est que sur ces systèmes, l'éditeur de liens peut regarder directement la Bibliothèque dynamique (la .so/.dynlib fichier) et comprendre ce qui est nécessaire sans une bibliothèque statique séparée comme sur Windows.

Pour charger une bibliothèque dynamiquement, vous n'avez pas besoin de lier avec quoi que ce soit lié à la bibliothèque que vous souhaitez charger.

2
répondu Some programmer dude 2014-04-05 08:36:08

Comme d'autres l'ont déjà dit: ce qui est inclus dans un fichier .lib sous Windows est inclus directement dans le .so/.dynlib sous Linux / OS X . Mais la question principale est... Pourquoi? La solution * nix n'est-elle pas meilleure ? Je pense que c'est le cas, mais le .lib a un avantage. Le développeur lié à la DLL n'a pas réellement besoin d'avoir accès au fichier DLL lui-même.

Un tel scénario arrive-t-il souvent dans le monde réel? Vaut - il la peine de maintenir deux fichiers par fichier DLL? Je n'ai pas savoir.

Edit: Ok, les gars, rendons les choses encore plus confuses! Vous pouvez lier directement à une DLL sous Windows, en utilisant MinGW. Donc, tout le problème de la bibliothèque d'importation n'est pas directement lié à Windows lui-même. Extrait de sampleDLL article de mingw wiki:

La bibliothèque d'importation créée par l'option de l'éditeur de liens" --out-implib " est obligatoire iff (==si et seulement si) la DLL doit être interfacée à partir de certains Compilateur C / c++ autre que la chaîne D'outils MinGW. Le MinGW la chaîne est parfaitement heureux de lier directement contre la DLL créée. Plus de détails peut être trouvé dans le ld.fichiers d'informations exe qui font partie des binutils package (qui fait partie de la chaîne d'outils).

2
répondu cubuspl42 2014-04-05 17:45:23

Linux nécessite également de lier, mais à la place contre un .Bibliothèque Lib il doit être lié à l'éditeur de liens dynamique /lib/ld-linux.so.2, mais cela se produit généralement dans les coulisses lors de L'utilisation de GCC (cependant, si vous utilisez un assembleur, vous devez le spécifier manuellement).

Les deux approches, soit les fenêtres .L'approche LIB ou L'approche Linux dynamic linker linking, sont considérées en réalité comme des liaisons statiques. Il y a, cependant, une différence que dans Windows une partie du travail est fait au moment du lien bien qu'il reste a du travail au moment du chargement (Je ne suis pas sûr, mais je pense que le .Le fichier LIB est simplement pour que l'éditeur de liens connaisse le nom de la bibliothèque physique, les symboles ne sont cependant résolus qu'au moment du chargement), tandis que sous Linux, tout ce qui est autre que le lien vers l'éditeur de liens dynamique se produit au moment du chargement.

La liaison dynamique se réfère généralement à ouvrir manuellement le fichier DLL au moment de l'exécution (par exemple en utilisant LoadLinrary()), auquel cas la charge est entièrement sur le programmeur.

1
répondu yoel halb 2014-04-05 08:40:08

Dans la bibliothèque partagée, par exemple .dll .dylib et .so, Il y a quelques informations sur le nom et l'adresse du symbole, comme ceci:

------------------------------------
| symbol's name | symbol's address |
|----------------------------------|
| Foo           | 0x12341234       |
| Bar           | 0xabcdabcd       |
------------------------------------

Et la fonction load, telle que LoadLibrary et dlopen, charge la bibliothèque partagée et la rend disponible à utiliser.

GetProcAddress et dlsym vous trouvez l'adresse du symbole. Par exemple:

HMODULE shared_lib = LoadLibrary("asdf.dll");
void *symbol = GetProcAddress("Foo");
// symbol is 0x12341234

Dans windows, il existe .lib fichier à utiliser .dll. Lorsque vous créez un lien vers ce fichier .lib, vous n'avez pas besoin d'appeler LoadLibrary et GetProcAddress, et utilisez simplement les bibliothèques partagées fonctionne comme si ce sont des fonctions "normales". Comment cela peut-il fonctionner?

En fait, le .lib contient une information d'importation . C'est comme ça:

void *Foo; // please put the address of Foo there
void *Bar; // please put the address of Bar there

Lorsque le système d'exploitation charge votre programme (à proprement parler, votre module ), le système d'exploitation exécute automatiquement LoadLibrary et GetProcAddress.

Et si vous écrivez du code tel que Foo();, le compilateur le convertit automatiquement en (*Foo)();. Vous pouvez donc les utiliser comme s'il s'agissait de fonctions" normales".

0
répondu ikh 2014-04-04 11:23:34