動態函式庫 (.so) 能減少磁碟/記憶體佔用、方便升級、提升 CPU 快取命中率。本文以 Ubuntu 14.04 + GCC 4.8 為例,完整示範 .so 編譯、鏈結、執行期載入路徑設定與常見錯誤排查。
lib名稱.so (可含版號,如 libfoo.so.1.0)。lib名稱.a。-fPIC (位置無關程式碼)、-shared (產生共享物件)。-l名稱 (省略 lib 前綴與 .so 後綴)。
/home/test/program/
├── myLibSrc.c # 函式庫原始碼
├── myLibInclude.h # 標頭檔
└── main.c # 測試主程式
#ifndef MYLIB_H
#define MYLIB_H
int myLibSrcFun(void);
#endif
#include
#include "myLibInclude.h"
int myLibSrcFun(void) {
printf("There is myLibSrcFun()\n");
return 0;
}
#include
#include "myLibInclude.h"
int main(int argc, char **argv) {
printf("Main function!\n");
myLibSrcFun(); // 呼叫動態庫函式
return 0;
}
cd /home/test/program
gcc -fPIC -shared -o libmyLib.so myLibSrc.c
# 或加入除錯資訊
gcc -fPIC -shared -g -DDEBUG -o libmyLib.so myLibSrc.c
-fPIC:產生位置無關程式碼,供多進程共享同一記憶體映射。-shared:指示連結器產生共享物件而非執行檔。
gcc -o app main.c /home/test/program/libmyLib.so
./app
# 輸出:
# Main function!
# There is myLibSrcFun()
cp libmyLib.so /usr/lib/libmyLib.so
gcc -o app main.c -lmyLib
編譯器會在 /usr/lib, /usr/local/lib, /lib 等標準路徑尋找 libmyLib.so。
LD_LIBRARY_PATH 環境變數指定的目錄 (最高優先)。/etc/ld.so.cache 快取 (由 ldconfig 產生)。/lib, /usr/lib (64-bit 為 /lib64, /usr/lib64)。
echo "/home/test/program" > /etc/ld.so.conf.d/myLib.conf
ldconfig
# 現在可直接 -lmyLib 鏈結,執行時也能找到
LD_LIBRARY_PATH=/home/test/program ./app
# 編譯時指定 soname
gcc -fPIC -shared -Wl,-soname,libmyLib.so.1 -o libmyLib.so.1.0 myLibSrc.c
# 建立符號連結
ln -sf libmyLib.so.1.0 libmyLib.so.1
ln -sf libmyLib.so.1 libmyLib.so
執行期載入器依 soname (此例 libmyLib.so.1) 尋找實際檔案,實現主版本相容、次版本升級。
#include
void *handle = dlopen("./libmyLib.so", RTLD_LAZY);
int (*func)(void) = dlsym(handle, "myLibSrcFun");
func();
dlclose(handle);
編譯需加 -ldl。適用於插件系統、熱插拔模組。
| 錯誤訊息 | 原因 | 解決 |
|---|---|---|
error while loading shared libraries: libmyLib.so: cannot open shared object file | 執行期找不到 .so | 設定 LD_LIBRARY_PATH、執行 ldconfig、或安裝至 /usr/lib |
/usr/bin/ld: cannot find -lmyLib | 編譯/鏈結期找不到 | 指定 -L/path/to/lib 或複製至標準目錄 |
undefined reference to `myLibSrcFun' | 函式簽名不符或未鏈結 | 確認標頭檔宣告、.c 定義、鏈結順序 |
