linux中的動態鏈結庫與靜態連線庫

2021-06-07 03:54:28 字數 3851 閱讀 6234

linux中建立靜態庫和動態庫

我們通常把一些公用函式製作成函式庫,供其它程式使用。函式庫分為靜態庫和動態庫兩種。靜態庫在程式編譯時會被連線到目標**中,

程式執行時將不再需要該靜態庫。動態庫在程式編譯時並不會被連線到目標**中,而是在程式執行是才被載入,因此在程式執行時還需要動態庫存在。

本文主要通過舉例來說明在linux中如何建立靜態庫和動態庫,以及使用它們。

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

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

hello.h(見程式1)為該函式庫的標頭檔案。

hello.c(見程式2)是函式庫的源程式,其中包含公用函式hello,該函式將在螢幕上輸出"hello ***!"。

main.c(見程式3)為測試庫檔案的主程式,在主程式中呼叫了公用函式hello。

程式1: hello.h

#ifndef hello_h

#define hello_h

void hello(const char *name);

#endif //hello_h

程式2: hello.c

#include

void hello(const char *name)

程式3: main.c

#include "hello.h"

int main()

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

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

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

# gcc -c hello.c #

(注2:首字元"#"是系統提示符,不需要鍵入,下文相同。)

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

# ls

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

(注3:首字元不是"#"為系統執行結果,下文相同。)

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

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

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

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

靜態庫時,需要注意這點。建立靜態庫用ar命令。

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

# ar cr 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. libmyhello.a

# ./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。

rm   

# 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命令將優先使用動態庫。

linux靜態鏈結庫與動態鏈結庫詳解

linux靜態鏈結庫與動態鏈結庫詳解 一順便說說了哦 通常情況下,對函式庫的鏈結是放在編譯時期 compile time 完成的.所有相關的物件檔案 object file 與牽涉到的函式庫 library 被鏈結合成乙個可執行檔案 executable file 程式在執行時,與函式庫再無瓜葛,因...

linux靜態鏈結庫與動態鏈結庫詳解

一順便說說了哦 通常情況下,對函式庫的鏈結是放在編譯時期 compile time 完成的.所有相關的物件檔案 object file 與牽涉到的函式庫 library 被鏈結合成乙個可執行檔案 executable file 程式在執行時,與函式庫再無瓜葛,因為所有需要的函式已拷貝到自己門下。所以...

動態鏈結庫與靜態鏈結庫

有人會想,動態鏈結這樣麻煩,為什麼還要用呢?這裡有乙個技術問題,對這個問題的解決直接導致了動態載入的需求。問題是有些dll只在某個windows版本中存在,或某個api只在某些windows版本中被加入指定的dll。當你使用靜態鏈結的.exe試圖在不支援的windows版本上執行時,系統會彈出系統對...