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

Linux 共享庫開發完整指南:建立 .so 與動態載入 (dlopen/dlsym)

     編輯:關於C++

共享庫與靜態庫比較

Linux 共享庫 (.so) 相當於 Windows DLL。優點:節省記憶體 (多程式共享同一實體)、支援動態更新、可執行檔體積較小。缺點:部署需確保庫檔案存在、版本相容性管理、啟動微小開銷。

建立共享庫

原始碼 mytestso.c


#include 
#include 

int GetMax(int a, int b) {
    return (a >= b) ? a : b;
}

int GetInt(char* pszTxt) {
    return (pszTxt == 0) ? -1 : atoi(pszTxt);
}

編譯指令


gcc -fPIC -shared mytestso.c -o mytestso.so
  • -fPIC (Position Independent Code):產生位置無關碼,共享庫必須。
  • -shared:輸出共享物件而非執行檔。

主程式動態載入與使用

原始碼 mytest.c


#include 
#include 
#include 

int main() {
    void* handle = dlopen("./mytestso.so", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "dlopen 失敗: %s\n", dlerror());
        exit(1);
    }

    // 取得函式位址並轉型為函式指標
    int (*GetMax)(int, int) = (int(*)(int,int)) dlsym(handle, "GetMax");
    int (*GetInt)(char*) = (int(*)(char*)) dlsym(handle, "GetInt");
    const char* err = dlerror();
    if (err) { fprintf(stderr, "dlsym 失敗: %s\n", err); exit(1); }

    printf("max=%d\n", GetMax(200, 600));
    printf("txt=%d\n", GetInt("1024"));

    dlclose(handle);
    return 0;
}

編譯指令


gcc mytest.c -ldl -o mytest
  • -ldl:連結 libdl 提供 dlopen/dlsym/dlclose/dlerror。

關鍵 API 詳細說明

函式用途關鍵參數
dlopen載入共享庫路徑、旗標: RTLD_LAZY (延遲解析) / RTLD_NOW (立即解析)
dlsym取得符號 (函式/變數) 位址Handle、符號名稱字串
dlerror取得最後錯誤訊息無參數,呼叫後清除錯誤狀態
dlclose卸載共享庫Handle,參考計數歸零時真正卸載

共享庫搜尋順序

  1. 環境變數 LD_LIBRARY_PATH 指定的目錄
  2. /etc/ld.so.cache 快取 (由 ldconfig 維護)
  3. /usr/lib, /lib
  4. 當前工作目錄 (視載入路徑是否含 ./)

建議安裝至標準目錄並執行 ldconfig,或設定 rpath 連結選項。

進階主題

  • 版本控制:libfoo.so.1.0 → libfoo.so.1 (soname) → libfoo.so (linker name)。
  • 符號可見性:-fvisibility=hidden 預設隱藏,配合 __attribute__((visibility("default"))) 匯出公共 API。
  • 建構/解構函式:__attribute__((constructor)) / (destructor) 在載入/卸載時自動執行。
  • C++ 名稱修飾:對外介面建議使用 extern "C" 避免修飾,或使用 c++filt 解碼。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved