Angenommen, Sie haben eine Klasse Unusefulwie folgt definiert:
Datei Unuseful.h:
class Unuseful {
public:
void printUnusefulStatement();
};
Datei Unuseful.cpp:
#include "unuseful.h"
#include <iostream>
void Unuseful::printUnusefulStatement()
{
std::cout << "Hello world!" << std::endl;
}
Jetzt haben Sie eine andere Klasse, die nicht nützliche Anweisungen drucken muss:
Unuseful u;
u.printUnusefulStatement();
Dies bedeutet, dass Sie eine externe Bibliothek verwenden möchten, die die spezifische Implementierung ( printUnusefulStatement) enthält, die Sie in Ihren Code aufnehmen möchten.
Sie können diese Bibliothek auf zwei Arten verwenden:
- Durch Bereitstellung des Quellcodes für den Compiler
- Durch Bereitstellen einer Binärdatei (die zuvor für Ihre Architektur kompiliert wurde) für den Linker
Fall 1: Verwenden einer Bibliothek zur Kompilierungszeit
Dies ist der einfachste Fall. Sie haben den Quellcode der Bibliothek, die Sie verwenden müssen, und müssen ihn einfach zusammen mit Ihrem vorhandenen Code (z. B. main.cppDatei) kompilieren . In der Regel sind Sie der Autor und Benutzer der Bibliothek (eine Klasse, die eine von Ihnen benötigte Aufgabe erfüllt).
Kompilieren mit diesem Befehl:
g++ main.cpp unuseful.cpp
ermöglicht es Ihnen, die Implementierung zu verwenden, die Sie in Ihrer main.cppDatei benötigen .
Fall 2: Verknüpfen einer Bibliothek
In den meisten Fällen als in Fall 1 verfügen Sie nicht über den Quellcode der Bibliothek, die Sie verwenden möchten. Sie haben nur die Header-Datei ( Unuseful.hum mit dem Beispiel fortzufahren) und eine statische oder gemeinsam genutzte Bibliothek (wahrscheinlich [*] libunuseful.abzw. libunuseful.soDateien).
Die statische Bibliothek ist ein Archiv von Objektdateien ( *.o), die in Ihren endgültigen ausführbaren Dateien verknüpft sind. Die gemeinsam genutzten Bibliotheken werden stattdessen dynamisch geladen - zur Laufzeit (auf dieser Seite finden Sie ein besseres Verständnis des Unterschieds).
Statische Bibliotheken werden durch einfaches Archivieren der *.oDateien mit dem arProgramm erstellt:
# Create the object files (only one here)
g++ -c unuseful.cpp
# Create the archive (insert the lib prefix)
ar rcs libunuseful.a unuseful.o
Freigegebene Bibliotheken werden mit der g++ -sharedOption erstellt:
# Create the object file with Position Independent Code[**]
g++ -fPIC -c unuseful.cpp
# Crate the shared library (insert the lib prefix)
g++ -shared -o libunuseful.so unuseful.o
Nehmen wir an, Sie haben jetzt die Unuseful.hDatei und die gemeinsam genutzte Bibliothek ( libunuseful.soDatei) und eine main.cppDatei, die ein UnusefulObjekt instanziiert und die printUnusefulStatementMethode aufruft .
Wenn Sie versuchen, diese Datei ( g++ main.cpp) zu kompilieren, beschwert sich der Linker, weil er das printUnusefulStatementSymbol nicht finden kann .
Es ist Zeit, die Bibliothek zu benutzen:
g++ main.cpp -L. -lunuseful
Die -LOption teilt dem Linker mit, wo nach Bibliotheksdateien gesucht werden soll, und das -lFlag teilt dem Linker den Namen der zu verwendenden Bibliotheken mit (ohne libPräfix).
Jetzt wird die ausführbare Datei erstellt ( a.outda ich keinen anderen Namen angegeben habe), und Sie haben eine Bibliothek verwendet, um eine von Ihnen benötigte Funktionalität zu implementieren ( printUnusefulStatement).
Da die gemeinsam genutzte Bibliothek zur Laufzeit geladen wird, schlägt die Ausführung der a.outausführbaren Datei möglicherweise fehl, da das System die Bibliothek nicht finden kann. In der Regel kann dies gelöst werden, indem eine Umgebungsvariable festgelegt wird, die angibt, welche Pfade für die Suche nach dynamischen Bibliotheken verwendet werden sollen:
# Set the LD_LIBRARY_PATH [*]
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
Fertig, jetzt wurde Ihre ausführbare Datei kompiliert und sie kann die benötigte Bibliothek ausführen und laden.
Fazit
Dies ist ein schneller Überblick über Bibliotheken, von denen ich hoffe, dass sie Ihnen helfen können, zu verstehen, wie sie verwendet und anderen zur Verfügung gestellt werden.
Es gibt viele, viele Aspekte, die bei Interesse genauer untersucht werden sollten: g++Optionen beim Erstellen von gemeinsam genutzten Bibliotheken, arOptionen, Umgebungsvariablen, das Format für gemeinsam genutzte Bibliotheken usw.
[*]: In einer Unix-Umgebung
[**]: Wenn dies für den Zielcomputer unterstützt wird, geben Sie positionsunabhängigen Code aus, der für die dynamische Verknüpfung geeignet ist und eine Begrenzung der Größe der globalen Versatztabelle vermeidet. Diese Option macht einen Unterschied bei m68k, PowerPC und SPARC. Positionsunabhängiger Code erfordert spezielle Unterstützung und funktioniert daher nur auf bestimmten Computern. [Von der g ++ Manpage]
std::cout << "Hello World";Sie eine Bibliothek. Könnten Sie genauer sein?