首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Qt Creator 開發動態庫完整教程:從 .so 創建到 GUI 專案調用實戰

     編輯:關於C語言

在 Linux 環境下,Qt Creator 內建完整工具鏈,開發與調用動態庫 (`.so`) 流程順暢。本文提供一個最小化完整範例:創建 C++ 動態庫專案、導出函數/類、編譯生成 `.so`,再創建 GUI 應用專案鏈接調用,涵蓋 `.pro` 配置、跨平台導出宏、外部符號解析等關鍵細節。

第一階段:創建動態庫專案 (`zsz`)

1. 專案創建

File → New Project → **Library** → **C++ Library** → 名稱 `zsz` → 完成。

2. 專案文件 `zsz.pro`


# -------------------------------------------------
# Project created by QtCreator
# -------------------------------------------------
TARGET = zz
TEMPLATE = lib
CONFIG += plugin          # 生成插件風格庫
DEPENDPATH += .
INCLUDEPATH += .

SOURCES += mylib.cpp
HEADERS += mylib.h

3. 導出頭文件 `mylib.h` — 跨平台導出宏關鍵


#ifndef MYLIB_H
#define MYLIB_H

// Windows: __declspec(dllexport/import)
// Linux/macOS: 符號默認可見,無需修飾
#ifdef Q_OS_WIN
#  define MY_EXPORT __declspec(dllexport)
#else
#  define MY_EXPORT
#endif

class MY_EXPORT MyLib {
public:
    int myMax(int a, int b);
    int add(int a, int b);
};

// C 鏈接自由函數,便於 C 調用或動態載入
extern "C" MY_EXPORT int diff(int a, int b);

#endif // MYLIB_H

注意:類方法若需導出,**類定義前**加 `MY_EXPORT`;`extern "C"` 防止 C++ 名字修飾,配合 `MY_EXPORT` 導出。

4. 實現文件 `mylib.cpp`


#include "mylib.h"

extern "C" MY_EXPORT int MyLib::myMax(int a, int b) {
    return (a >= b) ? a : b;
}

extern "C" MY_EXPORT int MyLib::add(int a, int b) {
    return a + b;
}

extern "C" MY_EXPORT int diff(int a, int b) {
    return (a >= b) ? (a - b) : (b - a);
}

5. 編譯生成

Build → Build Project `zsz` → 輸出目錄生成 `libzsz.so` (Linux) / `zsz.dll` (Windows)。

第二階段:創建 GUI 應用專案調用動態庫

1. 專案創建

File → New Project → **Application (Qt)** → **Qt Widgets Application** → 名稱 `use_zsz`。

2. 複製庫文件

將 `zsz` 專案輸出目錄下的 `mylib.h` 與 `libzsz.so` 複製到 `use_zsz` 專案根目錄 (與 `.pro` 同級)。

3. 應用專案文件 `use_zsz.pro`


# -------------------------------------------------
# Project created by QtCreator
# -------------------------------------------------
TARGET = use_zsz
TEMPLATE = app

QT += widgets svg        # 按需添加模組
DEPENDPATH += .
INCLUDEPATH += .         # 當前目錄含 mylib.h

# 鏈接動態庫:相對路徑指向複製的 .so
LIBS += -L. -lzsz        # 等價於 LIBS += ./libzsz.so

SOURCES += main.cpp
HEADERS += mylib.h

關鍵:`-L.` 告訴鏈接器當前目錄搜尋庫,`-lzsz` 鏈接 `libzsz.so` (Linux 命名慣例 `lib` + 名稱 + `.so`)。

4. 主程式 `main.cpp`


#include 
#include 
#include 
#include "mylib.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    QPushButton hello("Hello World! Dynamic Lib");
    hello.resize(400, 200);

    // 1. 類成員函數調用 (需庫導出類)
    MyLib lib;
    qDebug() << "Max(15, 9) =" << lib.myMax(15, 9);  // 15
    qDebug() << "Add(15, 9) =" << lib.add(15, 9);    // 24

    // 2. C 風格自由函數調用 (extern "C")
    qDebug() << "Diff(15, 9) =" << diff(15, 9);      // 6

    hello.show();
    return app.exec();
}

三、運行時動態庫查找機制 (Linux)

編譯鏈接成功不代表運行成功。Linux 動態鏈接器按順序搜尋:

  1. 可執行文件 `DT_RPATH` / `DT_RUNPATH` (鏈接器 `-rpath` 設置)
  2. 環境變量 `LD_LIBRARY_PATH`
  3. `/etc/ld.so.cache` 快取 (`/lib`, `/usr/lib` 等)
  4. 預設路徑 `/lib`, `/usr/lib`

三種部署方案

方案操作優點缺點
rpath (推薦開發/部署)`.pro` 加入 `QMAKE_LFLAGS += -Wl,-rpath,\\$$ORIGIN`相對執行檔路徑,免環境變量,安全需鏈接器支援
LD_LIBRARY_PATH`export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH`臨時測試方便污染環境,生產不推薦
系統目錄安裝`sudo cp libzsz.so /usr/local/lib && ldconfig`系統級可用需 root,版本管理麻煩

Qt Creator 專案模式下,構建後在構建目錄運行通常自動設置 `LD_LIBRARY_PATH`,直接點擊 Run 即可。發布時請採用 `rpath` 或打包腳本設置環境。

四、進階:類導出與 C++ ABI 兼容性警示

  • 類導出:如示例,整個類標記 `MY_EXPORT`,所有公開/保護成員自動導出。
  • ABI 風險:C++ 動態庫導出類強依賴**編譯器版本、標準庫實現、編譯選項**完全一致。跨 GCC 版本、GCC/Clang 混用、Debug/Release 混用極易崩潰。
  • 安全替代:對外僅導出 `extern "C"` 自由函數 + 不透明指標 (`void*`/`struct Opaque*`) + 工廠函數,內部用 C++ 實現。此即「C 接口、C++ 實現」模式,Qt 自身插件系統即採用此策略。

五、Windows 環境差異

  • 輸出文件:`zsz.dll` + `zsz.lib` (導入庫)。
  • `.pro` 鏈接:`LIBS += -L. -lzsz` 同理生效 (尋找 `zsz.lib`)。
  • 運行時:DLL 需放在 exe 同目錄或 `PATH` 目錄。
  • 宏定義:`Q_OS_WIN` 觸發 `__declspec(dllexport)`,構建庫時導出;使用庫時需定義 `MY_IMPORT` 為 `dllimport` (通常用共享頭文件配合 `BUILD_MYLIB` 宏自動切換)。

掌握此流程,你就能在 Qt Creator 中輕鬆實現模組化開發:核心邏輯封裝為動態庫,UI 層輕量調用,支援熱更新、插件架構與跨語言調用 (C/Python 等調用 `extern "C"` 接口)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved