Die Verknüpfung mit einer DLL-Datei kann implizit zur Kompilierungsverknüpfungszeit oder explizit zur Laufzeit erfolgen. In beiden Fällen wird die DLL in den Speicher des Prozesses geladen, und alle exportierten Einstiegspunkte stehen der Anwendung zur Verfügung.
Bei expliziter Verwendung zur Laufzeit verwenden Sie LoadLibrary()und GetProcAddress()zum manuellen Laden der DLL und zum Abrufen von Zeigern auf die Funktionen, die Sie aufrufen müssen.
Wenn beim Erstellen des Programms implizit eine Verknüpfung hergestellt wird, werden Stubs für jeden vom Programm verwendeten DLL-Export aus einer Importbibliothek mit dem Programm verknüpft, und diese Stubs werden aktualisiert, wenn EXE und DLL beim Start des Prozesses geladen werden. (Ja, ich habe hier mehr als ein bisschen vereinfacht ...)
Diese Stubs müssen von irgendwoher kommen, und in der Microsoft-Toolkette stammen sie aus einer speziellen Form einer .LIB-Datei, die als Importbibliothek bezeichnet wird . Die erforderliche .LIB wird normalerweise gleichzeitig mit der DLL erstellt und enthält einen Stub für jede aus der DLL exportierte Funktion.
Verwirrenderweise würde eine statische Version derselben Bibliothek auch als .LIB-Datei geliefert. Es gibt keine triviale Möglichkeit, sie voneinander zu unterscheiden, außer dass LIBs, die Importbibliotheken für DLLs sind, normalerweise kleiner (oft viel kleiner) sind als die passende statische LIB.
Wenn Sie die GCC-Toolchain verwenden, benötigen Sie übrigens keine Importbibliotheken, die Ihren DLLs entsprechen. Die auf Windows portierte Version des Gnu-Linkers versteht DLLs direkt und kann die meisten erforderlichen Stubs im laufenden Betrieb synthetisieren.
Aktualisieren
Wenn Sie einfach nicht widerstehen können, zu wissen, wo sich alle Schrauben und Muttern wirklich befinden und was wirklich los ist, gibt es bei MSDN immer etwas zu helfen. Matt Pietreks Artikel Ein detaillierter Blick auf das tragbare ausführbare Win32-Dateiformat bietet einen vollständigen Überblick über das Format der EXE-Datei und darüber, wie sie geladen und ausgeführt wird. Es wurde sogar aktualisiert, um .NET und mehr abzudecken, seit es ursprünglich im MSDN Magazine erschien. 2002.
Es kann auch hilfreich sein zu wissen, wie man genau lernt, welche DLLs von einem Programm verwendet werden. Das Tool dafür ist Dependency Walker, auch bekannt als abhängige.exe. Eine Version davon ist in Visual Studio enthalten, die neueste Version ist jedoch beim Autor unter http://www.dependencywalker.com/ erhältlich . Es kann alle DLLs identifizieren, die zur Verbindungszeit angegeben wurden (sowohl frühes Laden als auch verzögertes Laden), und es kann das Programm ausführen und nach zusätzlichen DLLs suchen, die es zur Laufzeit lädt.
Update 2
Ich habe einige der früheren Texte umformuliert, um sie beim erneuten Lesen zu verdeutlichen und die impliziten und expliziten Verknüpfungen der Kunstbegriffe zu verwenden , um die Konsistenz mit MSDN zu gewährleisten.
Wir haben also drei Möglichkeiten, Bibliotheksfunktionen zur Verwendung durch ein Programm zur Verfügung zu stellen. Die offensichtliche Folgefrage lautet dann: "Wie wähle ich welchen Weg?"
Durch statische Verknüpfung wird der Großteil des Programms selbst verknüpft. Alle Ihre Objektdateien werden aufgelistet und vom Linker in der EXE-Datei zusammengefasst. Unterwegs kümmert sich der Linker um kleinere Aufgaben wie das Korrigieren von Verweisen auf globale Symbole, damit Ihre Module die Funktionen des anderen aufrufen können. Bibliotheken können auch statisch verknüpft werden. Die Objektdateien, aus denen die Bibliothek besteht, werden von einem Bibliothekar in einer .LIB-Datei gesammelt, die der Linker nach Modulen sucht, die die benötigten Symbole enthalten. Ein Effekt der statischen Verknüpfung besteht darin, dass nur die Module aus der Bibliothek verknüpft werden, die vom Programm verwendet werden. andere Module werden ignoriert. Beispielsweise enthält die traditionelle C-Mathematikbibliothek viele Trigonometriefunktionen. Aber wenn Sie dagegen verlinken und verwendencos()Sie erhalten keine Kopie des Codes für sin()oder, es tan()sei denn, Sie haben auch diese Funktionen aufgerufen. Für große Bibliotheken mit zahlreichen Funktionen ist diese selektive Einbeziehung von Modulen wichtig. Auf vielen Plattformen wie eingebetteten Systemen kann die Gesamtgröße des zur Verwendung in der Bibliothek verfügbaren Codes im Vergleich zu dem Speicherplatz, der zum Speichern einer ausführbaren Datei auf dem Gerät verfügbar ist, groß sein. Ohne selektive Einbeziehung wäre es schwieriger, die Details der Erstellung von Programmen für diese Plattformen zu verwalten.
Wenn jedoch in jedem Programm eine Kopie derselben Bibliothek vorhanden ist, wird ein System belastet, auf dem normalerweise viele Prozesse ausgeführt werden. Mit der richtigen Art von virtuellem Speichersystem müssen Speicherseiten mit identischem Inhalt nur einmal im System vorhanden sein, können jedoch von vielen Prozessen verwendet werden. Dies schafft einen Vorteil für die Erhöhung der Wahrscheinlichkeit, dass die Seiten, die Code enthalten, in so vielen anderen laufenden Prozessen wie möglich mit einigen Seiten identisch sind. Wenn Programme jedoch statisch mit der Laufzeitbibliothek verknüpft sind, verfügt jedes Programm über einen anderen Funktionsmix, der die Speicherzuordnung an verschiedenen Speicherorten verarbeitet, und es gibt nicht viele gemeinsam nutzbare Codeseiten, es sei denn, es handelt sich um ein Programm, das für sich allein ist in mehr als prozess laufen. Die Idee einer DLL hat also einen weiteren großen Vorteil gebracht.
Eine DLL für eine Bibliothek enthält alle ihre Funktionen, die von jedem Client-Programm verwendet werden können. Wenn viele Programme diese DLL laden, können sie alle ihre Codepages gemeinsam nutzen. Jeder gewinnt. (Nun, bis Sie eine DLL mit einer neuen Version aktualisieren, aber das ist nicht Teil dieser Geschichte. Google DLL Hell für diese Seite der Geschichte.)
Die erste große Wahl bei der Planung eines neuen Projekts ist also die dynamische und statische Verknüpfung. Mit der statischen Verknüpfung müssen Sie weniger Dateien installieren und sind immun gegen die Aktualisierung einer von Ihnen verwendeten DLL durch Dritte. Ihr Programm ist jedoch größer und nicht ganz so gut wie das Windows-Ökosystem. Mit der dynamischen Verknüpfung müssen Sie mehr Dateien installieren. Möglicherweise haben Sie Probleme mit der Aktualisierung einer von Ihnen verwendeten DLL durch einen Drittanbieter, sind jedoch im Allgemeinen mit anderen Prozessen auf dem System freundlicher.
Ein großer Vorteil einer DLL ist, dass sie geladen und verwendet werden kann, ohne das Hauptprogramm neu zu kompilieren oder sogar neu zu verknüpfen. Auf diese Weise kann ein Drittanbieter (z. B. Microsoft und die C-Laufzeit) einen Fehler in seiner Bibliothek beheben und verteilen. Sobald ein Endbenutzer die aktualisierte DLL installiert hat, profitiert er sofort von dieser Fehlerbehebung in allen Programmen, die diese DLL verwenden. (Es sei denn, es bricht Dinge. Siehe DLL-Hölle.)
Der andere Vorteil ergibt sich aus der Unterscheidung zwischen implizitem und explizitem Laden. Wenn Sie sich die Mühe machen, explizit zu laden, war die DLL möglicherweise noch nicht einmal vorhanden, als das Programm geschrieben und veröffentlicht wurde. Dies ermöglicht Erweiterungsmechanismen, mit denen beispielsweise Plugins erkannt und geladen werden können.
lib /list xxx.libundlink /dump /linkermember xxx.lib. Siehe diese Frage zum Stapelüberlauf .