Der Zweck dieser Präsentation istDer Zweck, allen beizubringen, wie man statische Bibliotheken und dynamische Bibliotheken erstellt und verwendet, die Unterschiede zwischen statischen Bibliotheken und dynamischen Bibliotheken zu verstehen und zu wissen, wie man bei ihrer Verwendung auswählt. Wir werden nicht tief auf die zugrunde liegenden Formate und Speicherlayouts von statischen Bibliotheken und dynamischen Bibliotheken eingehen. Für Interessierte empfehlen wir ein Buch: „Selbstkultivierung von Programmierern – Linken, Laden und Bibliotheken“.

1. Was ist eine Bibliothek

Eine Bibliothek ist geschriebener, vorhandener, ausgereifter Code, der wiederverwendet werden kann.In der Realität hängt jedes Programm von vielen grundlegenden zugrunde liegenden Bibliotheken ab. Es ist unmöglich, dass jeder Code von Grund auf neu schreibt. Daher ist die Existenz von Bibliotheken von außergewöhnlicher Bedeutung.。

Im Wesentlichen ist eine Bibliothek eine binäre Form von ausführbarem Code, der vom Betriebssystem in den Speicher geladen und ausgeführt werden kann. Es gibt zwei Arten von Bibliotheken: statische Bibliotheken (.a, .lib) und dynamische Bibliotheken (.so, .dll).

Das sogenannte Statische und Dynamische bezieht sich auf das Linken. Sehen wir uns die Schritte an, um ein Programm in eine ausführbare Datei zu kompilieren:

clip_image002[4]

Abbildung: Kompilierungsprozess

2. Statische Bibliotheken

Sie wird "statische Bibliothek" genannt, weil während der Linkphase die vom Assembler erzeugten Objektdateien .o zusammen mit den referenzierten Bibliotheken in die ausführbare Datei gelinkt und gepackt werden. Daher wird die entsprechende Linkmethode als statisches Linken bezeichnet.

Think about it: a static library is linked together with object files generated by assembly into an executable, so the static library must be similar in format to .o files. In fact, a static library can be simply viewed aseine Gruppe von Objektdateien (.o/.objeine Sammlung von Dateien)Das heißt, eine Datei, die durch Komprimieren und Paketieren vieler Objektdateien entsteht. Zusammenfassung der Eigenschaften statischer Bibliotheken:

- Das Linken statischer Bibliotheken mit Funktionsbibliotheken erfolgt zur Kompilierzeit.

- Zur Laufzeit hat das Programm nichts mit der Funktionsbibliothek zu tun, was das Portieren erleichtert.

- Verschwendet Platz und Ressourcen, weil alle zugehörigen Objektdateien und beteiligten Funktionsbibliotheken zu einer einzigen ausführbaren Datei gelinkt werden.

Im Folgenden schreiben wir einige einfache C++-Klassen für grundlegende arithmetische Operationen, kompilieren sie in eine statische Bibliothek, damit andere sie verwenden können. Die Header-Datei sieht wie folgt aus:

StaticMath.h-Headerdatei
#pragma once
class StaticMath
{
public:
    StaticMath(void);
    ~StaticMath(void);
 
    static double add(double a, double b);//加法
    static double sub(double a, double b);//减法
    static double mul(double a, double b);//乘法
    static double div(double a, double b);//除法

    void print();
};

Under Linux, usear-Tools, und verwenden Sie unter Windows VSlib.exe, um die Objektdateien zusammen zu komprimieren und sie zu nummerieren und zu indizieren, um das Nachschlagen und Abrufen zu erleichtern. Die allgemeinen Schritte zum Erstellen einer statischen Bibliothek sind in der Abbildung dargestellt:

clip_image004[4]

Abbildung: Prozess zum Erstellen einer statischen Bibliothek

2.1. Erstellen und Verwenden statischer Bibliotheken unter Linux

2.1.1. Benennungsregeln für statische Bibliotheken unter Linux

Die Namenskonvention für statische Bibliotheken unter Linux muss "lib[your_library_name].a" lauten: lib ist das Präfix, in der Mitte steht der Name der statischen Bibliothek, und die Erweiterung ist .a.

2.1.2. Erstellen einer statischen Bibliothek (.a)

Aus dem obigen Ablauf können wir entnehmen, dass der Prozess zum Erstellen einer statischen Bibliothek unter Linux wie folgt abläuft:

- Zuerst die Codedatei in eine Objektdatei .o (StaticMath.o) kompilieren

g++ -c StaticMath.cpp

Hinweis: Verwenden Sie den Parameter -c; andernfalls wird sie direkt in eine ausführbare Datei kompiliert.

- Verwenden Sie dann das Tool ar, um die Objektdatei in eine statische Bibliotheksdatei .a zu packen

ar -crv libstaticmath.a StaticMath.o

Erzeugen der statischen Bibliotheklibstaticmath.a。

clip_image006[4]

Bei größeren Projekten werden Makefile-Dateien (und Projektmanagement-Tools wie CMake) geschrieben, um statische Bibliotheken zu erzeugen; die Eingabe mehrerer Befehle ist zu umständlich.

2.1.3. Verwenden statischer Bibliotheken

Schreiben Sie Testcode, der die oben erstellte statische Bibliothek verwendet:

Testcode:
#include "StaticMath.h"
#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << StaticMath::add(a, b) << endl;
    cout << "a - b = " << StaticMath::sub(a, b) << endl;
    cout << "a * b = " << StaticMath::mul(a, b) << endl;
    cout << "a / b = " << StaticMath::div(a, b) << endl;

    StaticMath sm;
    sm.print();

    system("pause");
    return 0;
}

Um eine statische Bibliothek unter Linux zu verwenden, müssen Sie beim Kompilieren nur den Suchpfad der statischen Bibliothek angeben (-L-Option) und den Namen der statischen Bibliothek angeben (weder lib-Präfix noch .a-Suffix erforderlich, -l-Option).

# g++ TestStaticLibrary.cpp -L../StaticLibrary -lstaticmath

clip_image008[4]

- -L: Gibt das Verzeichnis an, in dem sich die zu linkende Bibliothek befindet

- -l: Gibt die zum Linken benötigte dynamische Bibliothek an. Der Compiler hat eine implizite Namensregel, wenn er dynamische Bibliotheken sucht: Er fügt lib vor den angegebenen Namen und .a oder .so dahinter an, um den Bibliotheksnamen zu bestimmen.

2.2. Erstellen und Verwenden statischer Bibliotheken unter Windows

2.2.1. Erstellen einer statischen Bibliothek (.lib)

Wenn Sie die VS-Befehlszeile verwenden, um eine statische Bibliothek zu generieren, wird das Programm ebenfalls in zwei Schritten generiert:

- Kompilieren Sie zuerst unter Verwendung der Compileroption/cvonCl.exeden Code (cl /c StaticMath.cpp) und erstellen Sie eine Objektdatei namens "StaticMath.obj".

- Verwenden Sie dann den BibliotheksmanagerLib.exe, um den Code zu linken (lib StaticMath.obj) und erstellen Sie die statische Bibliothek StaticMath.lib.

Natürlich machen wir das normalerweise nicht so; es ist bequemer, die VS-Projekteinstellungen zu verwenden. Wenn Sie eine Win32-Konsolenanwendung erstellen, wählen Sie den Typ „Statische Bibliothek“ aus; öffnen Sie die Projekt-„Eigenschaftenseiten“ -> „Konfigurationseigenschaften“ -> „Allgemein“ und wählen Sie Statische Bibliothek als Konfigurationstyp aus.

clip_image010[4]

Abbildung: Eigenschafteneinstellungen des VS-Projekts für statische Bibliotheken

Erstellen Sie das Projekt, um die statische Bibliothek zu generieren.

2.2.2. Verwenden statischer Bibliotheken

Der Testcode ist derselbe wie unter Linux. Es gibt 3 Möglichkeiten, ihn zu verwenden:

Methode 1:

Verwendung einer statischen Bibliothek in VS:

- In den "Eigenschaftenseiten" des Projekts -> "Allgemeine Eigenschaften" -> "Framework und Verweise" -> "Verweis hinzufügen" wird das Dialogfeld "Verweis hinzufügen" angezeigt. Die Registerkarte "Projekt" listet die Projekte in der aktuellen Projektmappe und alle Bibliotheken auf, auf die verwiesen werden kann. Wählen Sie auf der Registerkarte "Projekt" StaticLibrary aus. Klicken Sie auf "OK".

clip_image012[4]

- Fügen Sie das Verzeichnis der Headerdatei StaticMath.h hinzu; Sie müssen den Pfad des Include-Verzeichnisses ändern. Öffnen Sie die "Eigenschaftenseiten" des Projekts -> "Konfigurationseigenschaften" -> "C/C++" -> "Allgemein", und geben Sie im Eigenschaftswert "Zusätzliche Includeverzeichnisse" den Pfad zu dem Verzeichnis ein, das die Headerdatei StaticMath.h enthält, oder navigieren Sie zu diesem Verzeichnis.

clip_image014[4]

Kompilieren und Ausführen OK.

clip_image015[4]

Abbildung: Testergebnis der statischen Bibliothek (VS)

Wenn die referenzierte statische Bibliothek kein Unterprojekt derselben Projektmappe ist, sondern eine statische Drittanbieterbibliothek (lib) und eine Headerdatei verwendet, kann die obige Methode nicht eingerichtet werden. Es gibt 2 weitere Methoden, die ebenfalls funktionieren.

Methode 2:

Öffnen Sie die "Eigenschaftenseiten" des Projekts -> "Konfigurationseigenschaften" -> "Linker" -> "Befehlszeile", und geben Sie den vollständigen Pfad der statischen Bibliothek ein.

clip_image017[4]

Methode 3:

- "Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "Linker" -> "Allgemein": Geben Sie in "Zusätzliche Bibliotheksverzeichnisse" das Verzeichnis ein, in dem sich die statische Bibliothek befindet;

- "Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "Linker" -> "Eingabe": Geben Sie in "Zusätzliche Abhängigkeiten" den Namen der statischen Bibliothek StaticLibrary.lib ein.

clip_image019[4]

3. Dynamische Bibliotheken

Aus der obigen Einführung geht hervor, dass statische Bibliotheken einfach zu verwenden und zu verstehen sind und auch den Zweck der Wiederverwendung von Code erfüllen. Warum brauchen wir dann noch dynamische Bibliotheken?

3.1. Warum werden dynamische Bibliotheken noch benötigt?

Der Bedarf an dynamischen Bibliotheken entsteht eigentlich durch die Eigenschaften statischer Bibliotheken.

- Platzverschwendung ist ein Problem bei statischen Bibliotheken.

clip_image021[4]

- Ein weiteres Problem ist, dass statische Bibliotheken Probleme bei Programmaktualisierungen, Bereitstellung und Veröffentlichung verursachen. Wenn die statische Bibliothek liba.lib aktualisiert wird, müssen alle Anwendungen, die sie verwenden, neu kompiliert und an Benutzer ausgeliefert werden (für Benutzer mag es eine sehr kleine Änderung sein, aber sie führt dazu, dass das gesamte Programm erneut heruntergeladen wird,vollständiges Update)。

Dynamische Bibliotheken werden zur Kompilierzeit nicht in den Objektcode eingebunden, sondern erst beim Ausführen des Programms geladen.Wenn verschiedene Anwendungen dieselbe Bibliothek aufrufen, wird im Speicher nur eine Instanz dieser gemeinsam genutzten Bibliothek benötigt., wodurch das Problem der Platzverschwendung vermieden wird. Dynamische Bibliotheken werden erst beim Ausführen des Programms geladen, was auch das Problem löst, das statische Bibliotheken bei Programmaktualisierungen, Bereitstellung und Veröffentlichung verursachen. Benutzer müssen nur die dynamische Bibliothek aktualisieren,inkrementelles Update.。

clip_image023[4]

Zusammenfassung der Eigenschaften dynamischer Bibliotheken:

- Dynamische Bibliotheken verschieben das Linken und Laden einiger Bibliotheksfunktionen auf den Zeitpunkt, zu dem das Programm ausgeführt wird.

- Sie ermöglicht die gemeinsame Nutzung von Ressourcen zwischen Prozessen. (Daher werden dynamische Bibliotheken auch als gemeinsam genutzte Bibliotheken bezeichnet.)

- Sie macht das Upgrade einiger Programme einfach.

- Sie kann sogar wirklich erreichen, dass Linken und Laden vollständig vom Programmierer im Programmcode gesteuert werden (explizites Aufrufen)。

Windows und Linux haben unterschiedliche ausführbare Dateiformate, daher gibt es einige Unterschiede beim Erstellen dynamischer Bibliotheken.

Unter Windows ist das ausführbare Dateiformat das PE-Format, und eine dynamische Bibliothek erfordert eineDllMain-Funktion als Initialisierungs-Einstiegspunkt. Üblicherweise benötigen Sie beim Deklarieren exportierter Funktionen _declspec(dllexport).keyword。

- Unter Linux haben mit gcc kompilierte ausführbare Dateien standardmäßig das ELF-Format.Es ist kein Initialisierungs-Einstiegspunkt erforderlich, und Funktionen benötigen auch keine speziellen Deklarationen.Dies macht die Entwicklung bequemer.

Anders als beim Erstellen einer statischen Bibliothek wird kein Packwerkzeug (ar, lib.exe) benötigt; Sie können eine dynamische Bibliothek direkt mit dem Compiler erstellen.

3.2. Dynamische Bibliotheken unter Linux erstellen und verwenden

3.2.1. Namenskonventionen für dynamische Bibliotheken unter Linux

Der Name einer dynamischen Linkbibliothek hat die Form libxxx.so, mit dem Präfix "lib" und dem Suffix ".so".

- Für die eigentliche Bibliotheksdatei hat jede Shared Library einen speziellen Namen namens "soname". Nachdem das Programm gestartet ist, verwendet es diesen Namen, um dem dynamischen Loader mitzuteilen, welche Shared Library geladen werden soll.

- Im Dateisystem ist soname nur ein Link auf die eigentliche dynamische Bibliothek. Für dynamische Bibliotheken hat jede Bibliothek außerdem einen weiteren Namen, den der Compiler verwenden kann. Es handelt sich um eine Linkdatei, die auf die eigentliche Bibliotheks-Image-Datei zeigt (lib+soname+.so).

3.2.2. Eine dynamische Bibliothek (.so) erstellen

Schreiben Sie den Code der dynamischen Bibliothek für arithmetische Operationen:

DynamicMath.h-Headerdatei
#pragma once
class DynamicMath
{
public:
        DynamicMath(void);
        ~DynamicMath(void); 

        static double add(double a, double b);//加法
        static double sub(double a, double b);//减法
        static double mul(double a, double b);//乘法
        static double div(double a, double b);//除法
        void print();
};

- Zuerst die Objektdatei erzeugen; an dieser Stelle die Compiler-Option -fpic hinzufügen.

g++ -fPIC -c DynamicMath.cpp

-fPIC erzeugt positionsunabhängigen Code (PIC), sodass er von mehreren Anwendungen gemeinsam genutzt werden kann.

- Dann die dynamische Bibliothek erzeugen; an dieser Stelle die Linker-Option -shared hinzufügen.

g++ -shared -o libdynmath.so DynamicMath.o

-shared gibt an, dass eine dynamische Linkbibliothek erzeugt wird.

clip_image025[4]

Tatsächlich können die beiden obigen Schritte in einem einzigen Befehl kombiniert werden:

g++ -fPIC -shared -o libdynmath.so DynamicMath.cpp

3.2.3. Verwenden dynamischer Bibliotheken

Schreiben Sie Testcode, der die dynamische Bibliothek verwendet:

Testcode:
#include "../DynamicLibrary/DynamicMath.h"

#include <iostream>
using namespace std;

int main(int argc, char* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();
    return 0;
}

Referenzieren Sie die dynamische Bibliothek und kompilieren Sie sie in eine ausführbare Datei (auf die gleiche Weise wie bei einer statischen Bibliothek):

g++ TestDynamicLibrary.cpp -L../DynamicLibrary -ldynmath

Führen Sie dann aus: ./a.out, und stellen Sie fest, dass tatsächlich ein Fehler gemeldet wird!!!

clip_image027[4]

Sie vermuten vielleicht, dass es daran liegt, dass sich die dynamische Bibliothek und das Testprogramm nicht im selben Verzeichnis befinden. Prüfen wir, ob das der Fall ist:

clip_image029[4]

Es wird immer noch ein Fehler gemeldet!!! Wie werden also Shared-Library-Dateien während der Ausführung gefunden?

1) Wenn das System ausführbaren Code lädt, kann es die Namen der Bibliotheken kennen, von denen er abhängt, aber es muss auch die absoluten Pfade kennen. An diesem Punkt wird der dynamische Linker/Loader des Systems benötigt.

2) Bei ausführbaren Programmen im ELF-Format erfolgt dies durch ld-linux.so*. Es durchsucht das DT_RPATH-Segment der ELF-Datei, die Umgebungsvariable LD_LIBRARY_PATH, die Dateiliste /etc/ld.so.cache sowie die Verzeichnisse /lib/ und /usr/lib der Reihe nach und lädt die Bibliotheksdatei nach dem Finden in den Speicher.

Wie man dafür sorgt, dass das System sie finden kann:

- Wenn sie unter /lib oder /usr/lib installiert ist, kann ld sie standardmäßig ohne zusätzliche Operationen finden.

- Wenn sie in einem anderen Verzeichnis installiert ist, müssen Sie sie zur Datei /etc/ld.so.cache hinzufügen. Die Schritte sind wie folgt:

- Bearbeiten Sie die Datei /etc/ld.so.conf und fügen Sie den Pfad zum Verzeichnis hinzu, das die Bibliotheksdatei enthält.

- Führen Sie ldconfig aus; dieser Befehl baut die Datei /etc/ld.so.cache neu auf.

Wir kopieren die erstellte dynamische Bibliothek nach /usr/lib und führen dann das Testprogramm aus.

clip_image031[4]

3.3. Erstellen und Verwenden dynamischer Bibliotheken unter Windows

3.3.1. Erstellen einer dynamischen Bibliothek (.dll)

Im Vergleich zu Linux ist das Erstellen einer dynamischen Bibliothek unter Windows etwas umständlicher. Zuerst benötigen Sie eine DllMain-Funktion als Initialisierungseinstiegspunkt (beim Erstellen einer Win32-Konsolenanwendung wird durch Auswahl des DLL-Typs diese Datei automatisch generiert):

dllmain.cpp-Einstiegsdatei
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Üblicherweise benötigen Sie beim Deklarieren exportierter Funktionen das Schlüsselwort _declspec(dllexport):

DynamicMath.h-Headerdatei
#pragma once
class DynamicMath
{
public:
    __declspec(dllexport) DynamicMath(void);
    __declspec(dllexport) ~DynamicMath(void);

    static __declspec(dllexport) double add(double a, double b);//加法
    static __declspec(dllexport) double sub(double a, double b);//减法
    static __declspec(dllexport) double mul(double a, double b);//乘法
    static __declspec(dllexport) double div(double a, double b);//除法

    __declspec(dllexport) void print();
};

Um eine dynamische Bibliothek zu generieren, müssen Sie die Projekteigenschaften festlegen. Öffnen Sie die Projekt-"Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "Allgemein", und wählen Sie "Dynamische Bibliothek" für den Konfigurationstyp.

clip_image033[4]

Abbildung: v Einstellungen für Projekteigenschaften der dynamischen Bibliothek

Erstellen Sie das Projekt, und die dynamische Bibliothek wird generiert.

3.3.2. Verwendung dynamischer Bibliotheken

Erstellen Sie ein Win32-Konsolentestprogramm:

TestDynamicLibrary.cpp Testprogramm
#include "stdafx.h"
#include "DynamicMath.h"

#include <iostream>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    double a = 10;
    double b = 2;

    cout << "a + b = " << DynamicMath::add(a, b) << endl;
    cout << "a - b = " << DynamicMath::sub(a, b) << endl;
    cout << "a * b = " << DynamicMath::mul(a, b) << endl;
    cout << "a / b = " << DynamicMath::div(a, b) << endl;

    DynamicMath dyn;
    dyn.print();

    system("pause");
    return 0;
}

Methode 1:

- Projekt "Eigenschaftenseiten" -> "Allgemeine Eigenschaften" -> "Framework und Verweise" -> "Verweis hinzufügen"; das Dialogfeld "Verweis hinzufügen" wird angezeigt. Die Registerkarte "Projekte" listet die Projekte in der aktuellen Projektmappe und alle Bibliotheken auf, auf die verwiesen werden kann. Wählen Sie auf der Registerkarte "Projekte" DynamicLibrary aus. Klicken Sie auf "OK".

clip_image035[4]

- Fügen Sie das Verzeichnis der Headerdatei DynamicMath.h hinzu; Sie müssen den Pfad des Include-Verzeichnisses ändern. Öffnen Sie das Projekt "Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "C/C++" -> "Allgemein". Geben Sie im Eigenschaftswert "Zusätzliche Include-Verzeichnisse" das Verzeichnis ein, das die Headerdatei DynamicMath.h enthält, oder navigieren Sie dorthin.

clip_image037[4]

Kompilieren und Ausführen OK.

clip_image038[4]

Abbildung: Testergebnisse der dynamischen Bibliothek (VS)

Methode 2:

- "Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "Linker" -> "Allgemein"; geben Sie unter Zusätzliche Bibliotheksverzeichnisse das Verzeichnis ein, das die dynamische Bibliothek enthält.

clip_image040[4]

- "Eigenschaftenseiten" -> "Konfigurationseigenschaften" -> "Linker" -> "Eingabe"; geben Sie unter Zusätzliche Abhängigkeiten DynamicLibrary.lib ein, das durch Kompilieren der dynamischen Bibliothek generiert wurde.

clip_image042[4]

Hier haben Sie vielleicht eine Frage: Warum hat eine dynamische Bibliothek auch eine DynamicLibrary.lib-Datei? Das heißt, ob es sich um eine statische Linkbibliothek oder eine dynamische Linkbibliothek handelt, letztendlich gibt es immer eine lib-Datei. Was ist also der Unterschied zwischen den beiden? Tatsächlich sind sie völlig unterschiedliche Dinge.

clip_image044[4]

Die Größe von StaticLibrary.lib beträgt 190KB, und die Größe von DynamicLibrary.lib beträgt 3KB. Die lib-Datei, die zu einer statischen Bibliothek gehört, wird alsstatische Bibliothekbezeichnet, und die lib-Datei, die zu einer dynamischen Bibliothek gehört, wird als [Importbibliothek] bezeichnet. Tatsächlich enthält eine statische Bibliothek selbst den eigentlichen ausführbaren Code, die Symboltabelle usw., währendbei einer Importbibliothek der eigentliche ausführbare Code in der dynamischen Bibliothek liegt; die Importbibliothek enthält nur die Adress-Symboltabelle und andere grundlegende Adressinformationen, damit das Programm die entsprechenden Funktionen finden kann.。

4. Expliziter Aufruf dynamischer Bibliotheken

Die oben vorgestellte Methode zur Verwendung dynamischer Bibliotheken ähnelt der für statische Bibliotheken und gehört zum impliziten Aufruf; beim Kompilieren werden die entsprechende Bibliothek und der Suchpfad angegeben. Tatsächlich können dynamische Bibliotheken auch explizit aufgerufen werden.[In derCSprache]ist das explizite Aufrufen einer dynamischen Bibliothek ein Kinderspiel!

4.1. Expliziter Aufruf dynamischer Bibliotheken unter Linux

#include <dlfcn.h> stellt die folgenden Schnittstellen bereit:

- void * dlopen(const char *pathname, int mode): Die Funktion öffnet die angegebene Datei der dynamischen Linkbibliothek im angegebenen Modus und gibt ein Handle an den aufrufenden Prozess zurück.

- void* dlsym(void* handle, const char* symbol): dlsym gibt die dem Symbol entsprechende Adresse basierend auf dem Handle der dynamischen Linkbibliothek (pHandle) und dem Symbol zurück. Mit dieser Funktion können Sie nicht nur Funktionsadressen, sondern auch Variablenadressen ermitteln.

- int dlclose(void *handle): dlclose wird verwendet, um die dynamische Linkbibliothek mit dem angegebenen Handle zu schließen. Erst wenn der Nutzungszähler dieser dynamischen Linkbibliothek 0 erreicht, wird sie tatsächlich vom System entladen.

- const char *dlerror(void): Wenn eine Operationsfunktion einer dynamischen Linkbibliothek fehlschlägt, kann dlerror Fehlerinformationen zurückgeben. Ein Rückgabewert von NULL zeigt an, dass die Operationsfunktion erfolgreich ausgeführt wurde.

4.2. Explizites Aufrufen dynamischer Bibliotheken unter Windows

Eine Anwendung muss einen Funktionsaufruf durchführen, um die DLL zur Laufzeit explizit zu laden. Um explizit eine Verknüpfung mit einer DLL herzustellen, muss die Anwendung:

- Rufen SieLoadLibraryauf (oder eine ähnliche Funktion), um die DLL zu laden und ein Modulhandle zu erhalten.

- Rufen SieGetProcAddressauf, um einen Funktionszeiger auf jede exportierte Funktion zu erhalten, die die Anwendung aufrufen muss. Da die Anwendung die Funktionen der DLL über Zeiger aufruft, erzeugt der Compiler keine externen Referenzen, sodass keine Verknüpfung mit einer Importbibliothek erforderlich ist.

- Rufen Sie nach der Verwendung der DLLFreeLibrary auf。

4.3. Zu beachtende Punkte beim expliziten Aufrufen dynamischer C++-Bibliotheken

Für C++ ist die Situation etwas komplizierter. Die Schwierigkeit beim expliziten Laden einer dynamischen C++-Bibliothekliegt zum Teil anC++-Name-Mangling;und zum Teil daran, dass keine geeigneteAPI bereitgestellt wirdzum Laden von Klassen, in C++ müssen Sie möglicherweise eine Klasse in der Bibliothek verwenden, was das Erstellen einer Instanz dieser Klasse erfordert, und das ist nicht einfach.

Name-ManglingDies kann mit extern "C" gelöst werden. C++ hat ein spezifisches Schlüsselwort, mit dem Funktionen mit C-Bindung deklariert werden: extern "C". Mit extern "C" deklarierte Funktionen verwenden den Funktionsnamen als Symbolnamen, genau wie C-Funktionen. Daher können nur Nicht-Member-Funktionen als extern "C" deklariert werden, und sie können nicht überladen werden. Trotz vieler Einschränkungen sind extern "C"-Funktionen immer noch sehr nützlich, weil sie genau wie C-Funktionen mit dlopen dynamisch geladen werden können. Der Qualifizierer extern "C" bedeutet nicht, dass im Inneren der Funktion kein C++-Code verwendet werden kann. Im Gegenteil, es ist immer noch eine vollständige C++-Funktion und kann alle C++-Funktionen und verschiedene Arten von Parametern verwenden.

Auch zur Frage, wie man Klassen aus dynamischen C++-Bibliotheken erhält, hier sind einige verwandte Artikel, aber ich empfehle dies nicht:

- "LoadLibrary ruft Klasse in DLL auf":http://www.cppblog.com/codejie/archive/2009/09/24/97141.html

- „C++ dlopen Mini-HOWTO“:http://blog.csdn.net/denny_233/article/details/7255673

Die "explizite" Verwendung von Klassen in dynamischen C++-Bibliotheken ist sehr umständlich und gefährlich; wenn implizite Verwendung möglich ist, verwenden Sie nicht explizit; wenn statisch möglich ist, verwenden Sie nicht dynamisch.

5. Anhang: Bibliotheksbezogene Befehle unter Linux

5.1. g++ (gcc)-Compiler-Optionen

- -shared: Gibt an, eine dynamische Linkbibliothek zu erzeugen.

- -static: Gibt an, eine statische Linkbibliothek zu erzeugen.

- -fPIC: Gibt an, in positionsunabhängigen Code zu kompilieren; wird zum Kompilieren von gemeinsam genutzten Bibliotheken verwendet. Die Objektdatei muss als positionsunabhängiger Code erstellt werden, was konzeptionell bedeutet, dass sie, wenn das ausführbare Programm sie lädt, überall im Speicher des ausführbaren Programms platziert werden können.

- -L.: Gibt das Verzeichnis an, in dem sich die zu linkende Bibliothek befindet.

- -l: Gibt die zur Linkzeit benötigte dynamische Bibliothek an. Der Compiler hat eine implizite Namensregel, wenn er nach dynamischen Linkbibliotheken sucht, nämlich "lib" vor den angegebenen Namen und ".a/.so" dahinter zu setzen, um den Bibliotheksnamen zu bestimmen.

- -Wall: Alle Warnmeldungen generieren.

- -ggdb: Diese Option erzeugt so viele von gdb nutzbare Debuginformationen wie möglich.

- -g: Der Compiler erzeugt während der Kompilierung Debuginformationen.

- -c: Nur die Vorverarbeitung, Kompilierung und Assemblierung aktivieren, das heißt, das Programm in eine Objektdatei (.o-Datei) umwandeln.

- -Wl,options: Die Parameter (options) an den Linker ld übergeben. Wenn options Kommas enthält, options in mehrere Optionen aufteilen und dann an das Linker-Programm übergeben.

5.2. Der nm-Befehl

Manchmal müssen Sie möglicherweise sehen, welche Funktionen in einer Bibliothek enthalten sind.nm-Befehl.Er kann alle in der Bibliothek vorkommenden Symbole ausgeben. Die Bibliothek kann entweder statisch oder dynamisch sein. Von nm werden viele Symbole aufgelistet, und es gibt drei häufige Typen:

- Ein Typ wird in der Bibliothek aufgerufen, ist aber nicht in der Bibliothek definiert (was bedeutet, dass Unterstützung aus anderen Bibliotheken benötigt wird), dargestellt durch U;

- Ein Typ sind in der Bibliothek definierte Funktionen, dargestellt durch T, was am häufigsten vorkommt;

- Ein Typ sind die sogenannten "weak"-Symbole. Obwohl sie in der Bibliothek definiert sind, können sie durch gleichnamige Symbole in anderen Bibliotheken überschrieben werden, dargestellt durch W.

$nm libhello.h

5.3. Der ldd-Befehl

lddDer Befehl kann die gemeinsam genutzten Bibliotheken anzeigen, von denen ein ausführbares Programm abhängt.Beispielsweise hängt die von uns geschriebene dynamische Arithmetikbibliothek von den folgenden Bibliotheken ab:

clip_image046[4]

6. Zusammenfassung

Der Unterschied zwischen den beiden ist,dass der Zeitpunkt, zu dem der Code geladen wird, unterschiedlich ist.。

- Statische Bibliotheken werden während der Programmkompilierung in den Objektcode eingebunden, und die statische Bibliothek wird beim Ausführen des Programms nicht mehr benötigt.Daher ist die Größe größer.。

- Dynamische Bibliotheken werden beim Kompilieren des Programms nicht in den Objektcode eingebunden, sondern erst geladen, wenn das Programm ausgeführt wird. Daher muss die dynamische Bibliothek zur Laufzeit des Programms vorhanden sein.Dadurch ist die Codegröße kleiner.。

Der Vorteil dynamischer Bibliotheken besteht darin, dass, wenn verschiedene Anwendungen dieselbe Bibliothek aufrufen, nur eine Instanz der gemeinsam genutzten Bibliothek im Speicher benötigt wird. Das bringt Vorteile, aber auch Probleme mit sich! Wie das klassische DLL-Hell-Problem. Wie man Probleme bei der Verwaltung dynamischer Bibliotheken vermeidet, kannst du selbst in relevanten Materialien nachschlagen.

7. Verwandte Tutorials

C++-Tutorial:http://www.w3cschool.cc/cplusplus/cpp-tutorial.html

Autor: Wu Qin
Quelle: http://www.cnblogs.com/skynet/