Wie besprochen wollen wir den Code aus dem vorherigen Beispiel dynamisch zu unserem Programm linken. Als Programm können wir folgendes verwenden:
#include <iostream> #include "point.hpp" int main() { Point p1(13.4f, 3.7f, -0.4f); std::cout << "X-Koordinate: " << p1.getX() << std::endl; p1.setX(p1.getY() * p1.getZ()); std::cout << "X-Koordinate: " << p1.getX() << std::endl; }
Es unterscheidet sich von der bisher gewöhnten Vorgehensweise nicht von den bisherigen Programmen.
Zunächst müssen wir aus unserer Point
-Implementierung zur dynamischen Library kompilieren. Das klingt wesentlich komplizierter, als es ist:
g++ -fPIC -shared -o libpoint.so point.cpp
Dabei muss der Dateiname der Library mit lib
beginnen und auf .so
enden. Entweder kopieren wir dieses Shared Object in den Standard-SharedObjekt-Ordner, oder müssen später den lokalen Pfad verwenden. Wie gewohnt können wir unser Programm erst einmal kompilieren:
g++ -c main.cpp
Der letzte Schritt ist auch hier das Linken. Dabei brauchen wir den Namen der Library (das zwischen lib
und .so
steht, in unserem Falle point
) und verwenden den Kommandoparameter -lBIBLIOTHEKSNAME
. Weitehrin müssen wir beachten, ob sich die Library im Standard-Pfad befindet oder nicht. Linken wir z.B. SDL, so genügt in der Regel -lSDL
, da sich die libSDL.so
dank Paketverwaltung im Standardpfad befindet. Dann sehe unser Fall so aus:
g++ -o main main.o -lpoint
Anschließend kann das Programm main
normal gestartet werden. Dabei muss sich die libpoint.so
sich im Standard-Ordner für SharedObjects befinden, sonst verweigert unser Programm den Betrieb.
Liegt das SharedObject lokal, müssen wir den Suchpfad mit angeben. Dies geschieht durch -L/pfad/zum/sharedobject/
. Auf linux-basierten Systemen können wir die Variable $PWD
verwenden, um das aktuelle Arbeitsverzeichnis zu ermitteln. Dies ist nützlich um sich Schreibarbeit zu ersparen.
g++ -o main main.o -lpoint -L$PWD
Anschließend könnten wir das Programm main
starten, werden aber die gleiche Meldung erhalten wie bereits angesprochen.
Auf Linux-Systemen wird in der Regel nie das Standardverzeichnis nach SharedObjects durchsucht. Jedoch lässt sich dieses Verhalten erzwingen:
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$PWD
Damit wird der Such-Pfad des Linkers ld
um das aktuelle Verzeichnis erweitert. Beispielsweise wird aus dem alten Suchpfad /usr/libs
so /usr/libs/:/opt/stuff/
, wenn wir uns im Verzeichnis /opt/stuff/
befinden. Anschließend startet main
ohne Ärger zu machen. Da diese Änderung des Suchpfades aber nicht dauerhaft ist, bleiben effektiv zwei Möglichkeiten
(a) Den Suchpfad dauerhaft zu ändern. Davon rate ich ab: geht man davon zu unbedacht um, verlangsamt dies das Laden anderer Programme, die dann verschiedene andere Suchpfade durchsuchen müssen.
(b) Den Suchpfad durch ein Shellskript modifizieren. So könnte beim Starten das lokale Verzeichnis hinzugefügt und nach Beendigung des Programms entfernt werden.
#/bin/bash # eine etwas "bashige" Variante des substring-Klassikers if [ "${LD_LIBRARY_PATH#*$PWD}" == "$LD_LIBRARY_PATH" ]; then # Lokales Verzeichnis hinzufügen export LD_LIBRARY_PATH=$PATH:$PWD fi # Eigentliches Programm aufrufen ./main # ggf. lokales Verzeichnis wieder aus dem Suchpfad entfernen # ... todo
Hinweis: chmod +x
nicht vergessen, damit das Skript ausführbar ist
Hinweise: Ich habe das folgende mit Wine probiert, da ich kein Windows mehr habe. Sollte sich die Vorgehensweise von einem echten Windows unterscheiden, kann ich das folgende gern noch einmal überarbeiten :)
Zunächst müssen wir aus unserer Point
-Implementierung zur dynamischen Library kompilieren. Das klingt wesentlich komplizierter, als es ist:
g++ -shared -o point.dll point.cpp -lmingw32
Anders als unter Linux kann der Dateiname der Library beliebig sein, muss jedoch auf .dll
enden. Dennoch muss die DLL auch hier im Standardverzeichnis liegen - oder man hilft beim Linken nach.
Wie gewohnt können wir unser Programm erst einmal kompilieren:
g++ -c main.cpp
Der letzte Schritt ist auch hier das Linken. Dabei brauchen wir den Namen der Library (ohne .dll
). Dazu sollte die DLL im Standardverzeichnis liegen.
g++ -o main.exe main.o -lpoint -lmingw32
Liegt die DLL nicht im Standardverzeichnis, müssen wir den Pfad angeben. Dies geschieht durch -LC:\pfad\zur\dll\
. Auf Windows-Systemen können wir die Variable %CD%
verwenden, um das aktuelle Arbeitsverzeichnis zu ermitteln. Dies ist nützlich um sich Schreibarbeit zu ersparen.
g++ -o main.exe main.o -L%CD% -lpoint -lmingw32
Anschließend kann das Programm main.exe
normal gestartet werden. Dabei kann sich die point.dll
sich im Standard-Ordner für DLLs befinden - muss sie aber nicht! Windows-Programme suchen auch im lokalen Verzeichnis nach DLLs. Somit bleibt uns ein Shell-Skript (vgl. unter Linux) erspart: unser Programm läuft auch so.