Dynamische Bibliotheken
Willemers Informatik-Ecke
Wenn Bibliotheken von mehreren Anwendungen verwendet werden, spart es Speicher und Plattenplatz, wenn man diese in dynamische Bibliotheken auslagern. Unter UNIX nennt man die dynamischen Bibliotheken Dynamic Libraries. Unter Windows benennt man sie nach ihrer Endung: DLL steht für Dynamic Link Library.

MS-Windows

Sie können mit jeder IDE ein DLL-Projekt erstellen, und damit wird Ihnen schon ein Großteil der Arbeit abgenommen. Die Wizzards erstellen Ihnen auch bereits eine Funktion namens DllEntryPoint(), die jede DLL enthalten muss. Sie müssen nur noch die Funktionen schreiben, auf die Sie von außen zugreifen wollen.

Funktionsattribute

Die Windows-DLLs sind nicht im C++-Format gehalten, sondern halten sich an die klassische C-Schnittstelle. Die Funktionen müssen vom Compiler so umgesetzt werden, dass die Schnittstelle der eines C-Compilers entspricht.

Als Beispiel wird eine Funktion fkt() verwendet, die einen Parameter und einen Rückgabewert vom Typ double hat. Der Borland-Compiler verwendet folgende Schreibweise:

__declspec(dllexport) double fkt(double w)
{
    ...

In Visual C++ von Microsoft sieht eine Funktion für eine DLL so aus:

extern "C" __declspec(dllexport) double __stdcall fkt(double w)
{
    ...
Nach der Generierung des Projekts entsteht eine Datei mit der Namenserweiterung .DLL, die bei der Ausführung des Programms im Arbeitsverzeichnis oder im Windows-Verzeichnis liegen muss. Daneben gibt es eine Import-Datei mit der Erweiterung .LIB, die vom aufrufenden Programm hinzugebunden werden muss, damit es die richtige DLL anfordert. Das funktioniert durch Eintrag der Datei in die Projekteinstellungen unter Bibliotheken. Das aufrufende Programm braucht dann noch den Prototyp, um die Funktion korrekt aufrufen zu können. Dieser lässt sich leicht aus der Funktion herleiten. Bei Borland C++ sieht der Prototyp so aus:

__declspec(dllexport) double fkt(double w);

Der eigentliche Aufruf unterscheidet sich nicht durch den Aufruf einer gewöhnlichen lokalen Funktion.

UNIX/Linux

Im Gegensatz dazu sind bei UNIX und Linux keine besonderen Vorkehrungen bei den Funktionen notwendig. Allerdings müssen die korrekten Compiler-Optionen eingesetzt werden. In den dynamischen Bibliotheken können auch C++-Konstrukte wie Klassen oder überladene Funktionen verwendet werden.

Beispiel

Die dynamische Bibliothek hello soll einfach ein Wort auf dem Bildschirm ausgeben.

[libhello.cpp]

#include <iostream>
using namespace std;

void print_hello()
{
    cout << "Hello" << endl;
}

Der Aufruf erfolgt durch das Programm usehello.cpp. Hier wurde der Prototyp der Funktion print_hello() direkt angegeben, der in größeren Programmen natürlich in einer Header-Datei abgelegt würde.

void print_hello();

int main()
{
   print_hello();
}

Das Geheimnis besteht hier also ausschließlich darin, wie die beiden Module übersetzt werden. Die Datei libhello.cpp wird zunächst in eine Objektdatei kompiliert. Dabei sorgt die Option -fPIC dafür, dass positionsunabhängiger Code erzeugt wird. Der zweite Aufruf bewirkt das Binden der Objektdatei als dynamische Bibliothek. Die zentrale Option ist hier -shared. Sie bewirkt, dass die neue Bibliothek als dynamische Bibliothek gebunden wird.

[Kommandos zur Erzeugung einer dynamischen Bibliothek]

c++ -fPIC -c libhello.cpp
c++ -shared -o libhello.so libhello.o -lc

Zu guter Letzt muss noch das Programm usehello.cpp übersetzt werden.

[Übersetzen des Hauptprogramms]

c++ usehello.cpp -L. -lhello

Vor einem Aufruf muss die Bibliothek allerdings noch in ein Verzeichnis geschafft werden, in dem unter Linux dynamische Bibliotheken abgelegt werden.

sudo cp libhello.so /usr/lib