Erstellen von gemeinsam genutzten Bibliotheken
In den folgenden Abschnitten werden einige Punkte aufgeführt, die beim Erstellen von gemeinsam genutzten Bibliotheken zu beachten sind.
Verwendung von Symbolen aus gemeinsam genutzten Bibliotheken
Symbole – Funktionen, Variablen oder Klassen –, die in gemeinsam genutzten Bibliotheken enthalten sind und von Clients wie Anwendungen oder anderen Bibliotheken verwendet werden sollen, müssen auf besondere Weise gekennzeichnet werden. Diese Symbole werden als öffentliche Symbole bezeichnet, die exportiert oder öffentlich sichtbar gemacht werden.
Die übrigen Symbole sollten von außen nicht sichtbar sein. Auf den meisten Plattformen werden sie von den Compilern standardmäßig ausgeblendet. Auf einigen Plattformen ist eine spezielle Compiler-Option erforderlich, um diese Symbole auszublenden.
Beim Kompilieren einer gemeinsam genutzten Bibliothek muss diese für den Export markiert werden. Um die gemeinsam genutzte Bibliothek von einem Client aus zu verwenden, ist auf einigen Plattformen möglicherweise auch eine spezielle Import-Deklaration erforderlich.
Je nach Zielplattform stellt Qt spezielle Makros zur Verfügung, die die erforderlichen Definitionen enthalten:
- Q_DECL_EXPORT müssen zu den Deklarationen der Symbole hinzugefügt werden, die beim Kompilieren einer gemeinsam genutzten Bibliothek verwendet werden.
- Q_DECL_IMPORT müssen zu den Deklarationen der Symbole hinzugefügt werden, die beim Kompilieren eines Clients verwendet werden, der die gemeinsam genutzte Bibliothek nutzt.
Nun müssen wir sicherstellen, dass das richtige Makro aufgerufen wird – unabhängig davon, ob wir die gemeinsam genutzte Bibliothek selbst kompilieren oder nur den Client, der die Bibliothek nutzt. In der Regel lässt sich dies durch Hinzufügen eines speziellen Headers lösen.
Nehmen wir an, wir möchten eine gemeinsam genutzte Bibliothek namens „mysharedlib“ erstellen. Eine spezielle Header-Datei für diese Bibliothek, „ mysharedlib_global.h “, sieht wie folgt aus:
#include <QtCore/QtGlobal>
#if defined(MYSHAREDLIB_LIBRARY)
# define MYSHAREDLIB_EXPORT Q_DECL_EXPORT
#else
# define MYSHAREDLIB_EXPORT Q_DECL_IMPORT
#endifIn jeder Header-Datei der Bibliothek geben wir Folgendes an:
#include "mysharedlib_global.h"
MYSHAREDLIB_EXPORT void foo();
class MYSHAREDLIB_EXPORT MyClass...Anschließend müssen wir sicherstellen, dass „ MYSHAREDLIB_LIBRARY “ beim Erstellen der Bibliothek selbst für den Compiler definiert ist. Dies erfolgt im Build-System der Bibliothek. Wenn wir CMake verwenden, erweitern wir das Ziel „shared library“ wie folgt:
target_compile_definitions(mysharedlib PRIVATE MYSHAREDLIB_LIBRARY)Wenn wir qmake verwenden, fügen wir
DEFINES += MYSHAREDLIB_LIBRARYzur Datei „ .pro “ der gemeinsam genutzten Bibliothek hinzu.
Hinweis: Die Bibliotheksassistenten in Qt Creator und Qt VS Tools bieten Ihnen ein Grundgerüst, das diese Einstellungen für Sie vornimmt.
Hinweise zu Header-Dateien
In der Regel binden Clients nur die öffentlichen Header-Dateien von gemeinsam genutzten Bibliotheken ein. Diese Bibliotheken werden bei der Bereitstellung möglicherweise an einem anderen Speicherort installiert. Daher ist es wichtig, andere interne Header-Dateien auszuschließen, die beim Erstellen der gemeinsam genutzten Bibliothek verwendet wurden.
Beispielsweise könnte die Bibliothek eine Klasse bereitstellen, die ein Hardwaregerät umschließt und ein Handle zu diesem Gerät enthält, das von einer Bibliothek eines Drittanbieters bereitgestellt wird:
#include <footronics/device.h>
class MyDevice {
private:
FOOTRONICS_DEVICE_HANDLE handle;
};Eine ähnliche Situation ergibt sich bei Formularen, die mit dem „ Qt Widgets Designer“ erstellt wurden, wenn Aggregation oder Mehrfachvererbung verwendet wird:
#include "ui_widget.h"
class MyWidget : public QWidget {
private:
Ui::MyWidget m_ui;
};Bei der Bereitstellung der Bibliothek sollte keine Abhängigkeit von den internen Header-Dateien „ footronics/device.h “ oder „ ui_widget.h “ bestehen.
Dies lässt sich vermeiden, indem man das in verschiedenen C++-Programmierhandbüchern beschriebene Idiom des Zeigers auf die Implementierung nutzt. Für Klassen mit Wert-Semantik sollte die Verwendung von ` QSharedDataPointer` in Betracht gezogen werden.
Binäre Kompatibilität
Damit Clients, die eine gemeinsam genutzte Bibliothek laden, korrekt funktionieren, muss das Speicherlayout der verwendeten Klassen exakt mit dem Speicherlayout der Bibliotheksversion übereinstimmen, die zum Kompilieren des Clients verwendet wurde. Mit anderen Worten: Die vom Client zur Laufzeit gefundene Bibliothek muss binärkompatibel mit der zur Kompilierungszeit verwendeten Version sein.
Dies ist in der Regel kein Problem, wenn es sich bei dem Client um ein in sich geschlossenes Softwarepaket handelt, das alle benötigten Bibliotheken enthält.
Wenn die Client-Anwendung jedoch auf eine gemeinsam genutzte Bibliothek angewiesen ist, die zu einem anderen Installationspaket oder zum Betriebssystem gehört, müssen wir uns ein Versionsschema für gemeinsam genutzte Bibliotheken überlegen und entscheiden, auf welcher Ebene die Binärkompatibilität gewahrt werden soll. Beispielsweise sind Qt-Bibliotheken mit derselben Hauptversionsnummer garantiert binärkompatibel.
Die Wahrung der Binärkompatibilität schränkt die Änderungen ein, die Sie an den Klassen vornehmen können. Eine gute Erläuterung finden Sie unter KDE – Richtlinien/Probleme der Binärkompatibilität mit C++. Diese Aspekte sollten bereits zu Beginn des Bibliotheksentwurfs berücksichtigt werden. Wir empfehlen, das Prinzip der Informationsverbergung und die Technik des Zeigers auf die Implementierung wo immer möglich anzuwenden.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.