觀察 Windows 程序目錄會發現:主程式 .exe 往往只有幾百 KB,伴隨大量 .dll 文件。這些動態鏈接庫 (共享庫) 的優勢在於:
.dll,無需重新安裝整個應用。雖然動態鏈接比靜態鏈接有微小性能損耗,但現代硬件下完全可忽略。
QtGui / QtWidgets)。Qt Creator 自動生成關鍵文件:{ProjectName}_global.h —— 導出/導入宏定義。
// lib_global.h
#ifndef LIB_GLOBAL_H
#define LIB_GLOBAL_H
#include <QtCore/qglobal.h>
#if defined(LIB_LIBRARY)
# define LIBSHARED_EXPORT Q_DECL_EXPORT // 構建庫時:導出符號
#else
# define LIBSHARED_EXPORT Q_DECL_IMPORT // 使用庫時:導入符號
#endif
#endif // LIB_GLOBAL_H
Q_DECL_EXPORT/Q_DECL_IMPORT 映射到平台特定關鍵字 (Windows: __declspec(dllexport/dllimport),Linux/GCC: __attribute__((visibility("default"))))。
// lib.h
#ifndef LIB_H
#define LIB_H
#include <QMainWindow>
#include "lib_global.h"
class LIBSHARED_EXPORT MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = nullptr);
};
#endif // LIB_H
// lib.cpp
#include "lib.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
// 初始化 UI 等
}
關鍵點:類聲明前加 LIBSHARED_EXPORT,構建時定義 LIB_LIBRARY 宏 (`.pro` 自動處理)。
編譯後在 debug/ (或 release/) 目錄獲得:
lib.dll —— Windows 動態庫liblib.a —— 導入庫 (MinGW) / lib.lib (MSVC),鏈接時需要TARGET = test
TEMPLATE = app
SOURCES += main.cpp
INCLUDEPATH += ../lib # 頭文件搜索路徑
LIBS += -L../lib/debug -llib # 庫文件搜索路徑 + 庫名 (去掉前綴 lib 及後綴 .dll/.a)
或直接指定完整路徑:LIBS += ../lib/debug/lib.dll (qmake 自動處理)。
#include <QtWidgets/QApplication>
#include "lib.h" // 來自共享庫的頭文件
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w; // 類定義在 lib.dll 中
w.show();
return a.exec();
}
編譯鏈接成功 ≠ 運行成功。 Windows DLL 搜索順序:
.exe 同級目錄)System32, SysWOW64)PATH 指定的目錄解決方案:將構建生成的 lib.dll 複製到應用程序 .exe 同級目錄,或配置 PATH,或使用 windeployqt 自動部署。
test.exe,彈出來自 lib.dll 的 MainWindow 窗口。lib.dll。lib.dll 覆蓋舊文件,重新運行 test.exe —— 無需重新編譯主程式,新功能即時生效。這正是 Qt 自身採用的插件/模塊化架構原理 (如 QtGui.dll, QtCore.dll)。
| 階段 | 關鍵動作 |
|---|---|
| 創建庫 | Qt Creator → Shared Library → 加 LIBSHARED_EXPORT 宏 |
| 構建庫 | 生成 .dll + 導入庫 .a/.lib |
| 使用庫 | .pro 添加 INCLUDEPATH + LIBS → #include "lib.h" → 實例化類 |
| 部署 | .dll 放至 .exe 同目錄 (或配置 PATH) |
掌握共享庫開發,是構建模塊化、可維護、支援熱更新的 Qt 應用的基礎技能。