linux 編譯靜態鏈結庫和動態鏈結庫

2021-05-28 00:07:17 字數 3745 閱讀 3949

我們通常把一些公用函式製作成函式庫,供其它程式使用。函式庫分為靜態庫和動態庫兩種。靜態庫在程式編譯時會被連線到目標**中,程式執行時將不再需要該靜態庫。動態庫在程式編譯時並不會被連線到目標**中,而是在程式執行是才被載入,因此在程式執行時還需要動態庫存在。本文主要通過舉例來說明在linux中如何建立靜態庫和動態庫,以及使用它們。

在建立函式庫前,我們先來準備舉例用的源程式,並將函式庫的源程式編譯成.o檔案。

第1步:編輯得到舉例的程式--hello.h、hello.c和main.c;

hello.c(見程式2)是函式庫的源程式,其中包含公用函式hello,該函式將在螢幕上輸出"hello ***!"。hello.h(見程式1)為該函式庫的標頭檔案。main.c(見程式3)為測試庫檔案的主程式,在主程式中呼叫了公用函式hello。

#ifndef hello_h

#define hello_h

void hello(const char *name);

#endif //hello_h

複製**

程式1: hello.h

#include

void hello(const char *name)

複製**

程式2: hello.c

#include "hello.h"

int main()

複製**

程式3: main.c

第2步:將hello.c編譯成.o檔案;

無論靜態庫,還是動態庫,都是由.o檔案建立的。因此,我們必須將源程式hello.c通過g

cc先編譯成.o檔案。

在系統提示符下鍵入以下命令得到hello.o檔案。

# gcc -c hello.c

#我們執行ls命令看看是否生存了hello.o檔案。

# ls

hello.c hello.h hello.o main.c

#在ls命令結果中,我們看到了hello.o檔案,本步操作完成。

下面我們先來看看如何建立靜態庫,以及使用它。

第3步:由.o檔案建立靜態庫;

靜態庫檔名的命名規範是以lib為字首,緊接著跟靜態庫名,擴充套件名為.a。例如:我們將建立的靜態庫名為myhello,則靜態庫檔名就是libmyhello.a。在建立和使用靜態庫時,需要注意這點。建立靜態庫用ar命令。

在系統提示符下鍵入以下命令將建立靜態庫檔案libmyhello.a。

# ar crv libmyhello.a hello.o

#我們同樣執行ls命令檢視結果:

# ls

hello.c hello.h hello.o libmyhello.a main.c

#ls命令結果中有libmyhello.a。

第4步:在程式中使用靜態庫;

靜態庫製作完了,如何使用它內部的函式呢?只需要在使用到這些公用函式的源程式中包含這些公用函式的原型宣告,然後在用gcc命令生成目標檔案時指明靜態庫名,gcc將會從靜態庫中將公用函式連線到目標檔案中。注意,gcc會在靜態庫名前加上字首lib,然後追加副檔名.a得到的靜態庫檔名來查詢靜態庫檔案。

在程式3:main.c中,我們包含了靜態庫的標頭檔案hello.h,然後在主程式main中直接呼叫公用函式hello。下面先生成目標程式hello,然後執行hello程式看看結果如何。

(# gcc -o hello main.c -l. -lmyhello??)

#gcc main.c libmyhello.a -o main

# ./hello

hello everyone!

#我們刪除靜態庫檔案試試公用函式hello是否真的連線到目標檔案 hello中了。

# rm libmyhello.a

rm: remove regular file `libmyhello.a'? y

# ./hello

hello everyone!

#程式照常執行,靜態庫中的公用函式已經連線到目標檔案中了。

我們繼續看看如何在linux中建立動態庫。我們還是從.o檔案開始。

第5步:由.o檔案建立動態庫檔案;

動態庫檔名命名規範和靜態庫檔名命名規範類似,也是在動態庫名增加字首lib,但其擴充套件名為.so。例如:我們將建立的動態庫名為myhello,則動態庫檔名就是libmyhello.so。用gcc來建立動態庫。

在系統提示符下鍵入以下命令得到動態庫檔案libmyhello.so。

# gcc -shared -fpci -o libmyhello.so hello.o

#我們照樣使用ls命令看看動態庫檔案是否生成。

# ls

hello.c hello.h hello.o libmyhello.so main.c

#第6步:在程式中使用動態庫;

在程式中使用動態庫和使用靜態庫完全一樣,也是在使用到這些公用函式的源程式中包含這些公用函式的原型宣告,然後在用gcc命令生成目標檔案時指明動態庫名進行編譯。我們先執行gcc命令生成目標檔案,再執行它看看結果。

# gcc -o hello main.c -l. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: no such file or directory

#哦!出錯了。快看看錯誤提示,原來是找不到動態庫檔案libmyhello.so。程式在執行時,會在/usr/lib和/lib等目錄中查詢需要的動態庫檔案。若找到,則載入動態庫,否則將提示類似上述錯誤而終止程式執行。我們將檔案libmyhello.so複製到目錄/usr/lib中,再試試。

# mv libmyhello.so /usr/lib

# ./hello

hello everyone!

#成功了。這也進一步說明了動態庫在程式執行時是需要的。

我們回過頭看看,發現使用靜態庫和使用動態庫編譯成目標程式使用的gcc命令完全一樣,那當靜態庫和動態庫同名時,gcc命令會使用哪個庫檔案呢?抱著對問題必究到底的心情,來試試看。

先刪除除.c和.h外的所有檔案,恢復成我們剛剛編輯完舉例程式狀態。

# rm -f hello hello.o /usr/lib/libmyhello.so

# ls

hello.c hello.h main.c

#在來建立靜態庫檔案libmyhello.a和動態庫檔案libmyhello.so。

# gcc -c hello.c

# ar cr libmyhello.a hello.o

# gcc -shared -fpci -o libmyhello.so hello.o

# ls

hello.c hello.h hello.o libmyhello.a libmyhello.so main.c

#通過上述最後一條ls命令,可以發現靜態庫檔案libmyhello.a和動態庫檔案libmyhello.so都已經生成,並都在當前目錄中。然後,我們執行gcc命令來使用函式庫myhello生成目標檔案hello,並執行程式 hello。

# gcc -o hello main.c -l. -lmyhello

# ./hello

./hello: error while loading shared libraries: libmyhello.so: cannot open shared object file: no such file or directory

#從程式hello執行的結果中很容易知道,當靜態庫和動態庫同名時, gcc命令將優先使用動態庫。

靜態鏈結庫和動態鏈結庫

其實再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上面比較理論的。實際用函式庫的時候主要分為,靜態庫和動態庫,這裡就簡簡單單地...