靜態鏈結庫和動態鏈結庫的區別

2021-08-19 08:50:08 字數 2922 閱讀 4083

靜態鏈結庫和動態鏈結庫的區別

一、靜態鏈結庫

預編譯->編譯->彙編->鏈結

linux:

生成目標檔案

g++ -c source.cpp -o source.o

打包成靜態鏈結庫

ar -crv source.a source.o

使用靜態鏈結庫

g++ test.cpp -l靜態鏈結庫目錄 -l靜態鏈結庫名稱沒有字尾

二、動態鏈結庫

使用動態鏈結庫是為了規避靜態鏈結庫的兩個問題。

乙個是多個副本的問題,對於靜態庫都是在編譯時刻將其編譯到源**當中,在執行時刻不會再和靜態庫有任何關係。這樣的好處是快,但是造成了空間的浪費

linux平台:

生成目標檔案

g++ -fpic source.cpp -o source.o

動態鏈結庫

g++ -shared source.so source.o

或者合併為乙個命令

g++ -fpic -shared source.so source.cpp

關於在使用中定位動態鏈結庫的位置,需要注意一些問題,預設動態鏈結庫是在/lib 或者 /usr/lib之下的

如果要在其他資料夾之下,需要修改 /etc/ld.so.cache檔案

動態鏈結庫的使用

動態鏈結庫與普通的程式相比而言,沒有main函式,是一系列函式的實現。通過shared和fpic編譯引數生產so動態鏈結庫檔案。程式在呼叫庫函式時,只需要連線上這個庫即可。例如下面實現乙個簡單的整數四則運輸的動態鏈結庫,定義的caculate.h和caculate.c兩個檔案,生產libcac.so動態鏈結庫。

程式**如下:

/*

caculate.h

*/#ifndef caculate_head_

#define caculate_head_

//加法

int add(int a, int

b);//

減法int sub(int a, int

b);//

除法int div(int a, int

b);//

乘法int mul(int a, int

b);#endif

/*caculate.c檔案*/

#include "

caculate.h"//

求兩個數的和

int add(int a, int

b)//

減法int sub(int a, int

b)//

除法int div(int a, int

b)//

乘法int mul(int a, int

b)

編譯生產libcac.so檔案如下:gcc -shared -fpic caculate.c -o libcac.so

編寫乙個測試程式呼叫此動態鏈結庫的函式,程式如下所示:

#include #include 

"caculate.h

"int

main()

編譯生產可執行檔案main如下:gcc main.c -o main -l ./ -lcac

(其中-l指明動態鏈結庫的路徑,-l後是鏈結庫的名稱,省略lib)

程式執行結果如下所示:

3、獲取動態鏈結庫的函式

linux提供dlopen、dlsym、dlerror和dlcolose函式獲取動態鏈結庫的函式。通過這個四個函式可以實現乙個外掛程式,方便程式的擴充套件和維護。函式格式如下所示:

#include void *dlopen(const

char *filename, int

flag);

char *dlerror(void

);void *dlsym(void *handle, const

char *symbol);

int dlclose(void *handle);

link with -ldl.

dlopen()是乙個強大的庫函式。該函式將開啟乙個新庫,並把它裝入記憶體。該函式主要用來載入庫中的符號,這些符號在編譯的時候是不知道的。寫個測試程式呼叫上面生產libcac.so庫如下所示:

#include #include 

#define dll_file_name "libcac.so"

intmain()

func = dlsym(handle, "

add"

); printf(

"%d + %d = %d\n

", a, b, func(a, b));

func = dlsym(handle, "

sub"

); printf(

"%d + %d = %d\n

", a, b, func(a, b));

func = dlsym(handle, "

div"

); printf(

"%d + %d = %d\n

", a, b, func(a, b));

func = dlsym(handle, "

mul"

); printf(

"%d + %d = %d\n

", a, b, func(a, b));

dlclose(handle);

return0;

}

程式執行結果如下所示:gcc call_main.c -o call_main -ldl

靜態鏈結庫和動態鏈結庫

其實再vc中,我們所用得所有api函式都封裝再下列三個dll檔案中 kernel32.dll 用於管理記憶體,程序和執行緒得各個函式 user32.dll 用於執行使用者介面任務,如視窗的建立和訊息的傳遞的各個函式 gdi32.dll 用於顯示文字和畫圖的各個函式 動態鏈結庫 我們再使用動態庫的時候...

靜態鏈結庫和動態鏈結庫

靜態鏈結庫 win32 static library 呼叫libtest.lib 動態dll win32 dynamic link library 跟librest的生成是一樣的 動態呼叫 成的.lib 和.dll 檔案拷入dllcall 工程所在的路徑,dllcall 執行下列 dll 中匯出函式...

靜態鏈結庫和動態鏈結庫

以前的時候寫過這方面的部落格,當時寫的時候都覺得已經懂了。今天閒著沒事幹,和咚哥他們去大華校招筆試遇到了這個問題。我突然間發現sdk沒寫三個月,把dll都忘記了。回來看了下,複習下。以前寫過程式的裝載和鏈結的部落格,那是os上面比較理論的。實際用函式庫的時候主要分為,靜態庫和動態庫,這裡就簡簡單單地...