Linux下靜態庫和動態庫的建立和使用

2021-10-08 22:38:58 字數 4842 閱讀 2737

由於windowslinux的平台不同(主要是編譯器、彙編器和聯結器的不同),因此二者庫的二進位制是不相容的),本文僅僅介紹linux系統下的庫。

庫就是寫好的現有的,成熟的,可以復用的**。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的**都從零開始,因此庫的存在意義非同尋常。

本質上來說庫是一種可執行**的二進位制形式,可以被作業系統載入記憶體執行。

庫有兩種:靜態庫(.a.lib)和動態庫(.so.dll)。windows上對應的是.lib.dlllinux上對應的是.a.so

本文主要講解linux下的靜態庫和動態庫的建立和使用。

gcc -c ***.c -o ***.o:這個命令就是將我們編寫的原始檔***.c(.c檔案或者是.cpp檔案) 編譯為目標檔案***.o(.o檔案)。

gcc ***1.o ***2.o -o ***.out:將上面生成的多個.o檔案鏈結生成乙個可執行檔案***.out。不加-o選項預設生成的可執行檔名為a.out

首先準備好測試**:我們這裡使用vscode編寫三個檔案 :hello.hhello.cmain.c檔案。

檔案的結構也是我們最熟悉的,檔案結構如下:

|-- hello.h

|-- hello.c

|-- main.c

hello.h這個標頭檔案中我們只宣告函式printhel而不定義,而是在hello.c原始檔中進行定義, 而在main.c中呼叫該函式。

三個程式檔案**如下:

hello.h標頭檔案包含的是函式的宣告:

hello.h

#ifndef hello_h_

#define hello_h_

void

printhel()

;#endif

hello.c包含的是標頭檔案的中宣告函式的定義:

hello.c

#include

"hello.h"

#include

void

printhel()

main.c檔案中呼叫了該函式:

/main.c./

#include

#include

"hello.h"

intmain()

至此,我們的測試**就準備好了,雖然很簡單,但是還是能說明問題的,下面繼續。

處理思路:

我們有幾種方法編譯這幾個檔案生成最終的可執行檔案:

1) 通過編譯多個原始檔,直接將目標**合成乙個.o檔案。

2) 通過建立靜態鏈結庫libhel.a,使得main函式呼叫printhel函式時可呼叫靜態鏈結庫。

3)通過建立動態鏈結庫libhel.so,使得main函式呼叫printhel函式時可呼叫靜態鏈結庫。

編譯hello.c:

# gcc -c hello.c -o hello.o
會生成hello.o目標檔案。

同理編譯main.c

# gcc -c main.c -o main.o
會生成main.o目標檔案。

# gcc hello.o main.o -o execuate
會生成execuate這個檔案。

執行可執行檔案:

# ./execuate

hello!

至此,我們的編譯工作就算是完成了,但是如果工程很大的話,有多個標頭檔案和原始檔的話,這樣編譯很麻煩,而且產生的可執行檔案很大,會造成空間浪費。最好的方法就是將hello.c編譯為庫,其中的函式就成為了庫函式。這和math庫沒有什麼區別。

下面我們會僅此呢個實操,將原始檔編譯成靜態庫和動態庫。

有了上面的基礎之後,我們分別介紹一下什麼是靜態庫,什麼是動態庫,下面先介紹靜態庫。

之所以稱為 「靜態庫」,是因為在鏈結階段,會將彙編生成的目標檔案.o與引用到的庫一起鏈結打包到可執行檔案中。因此對應的鏈結方式稱為靜態鏈結。

試想一下,靜態庫與彙編生成的目標檔案一起鏈結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實乙個靜態庫可以簡單看成是一組目標檔案(.o檔案)的集合,即很多目標檔案經過壓縮打包後形成的乙個檔案。

靜態庫特點總結:

靜態庫對函式庫的鏈結是放在編譯時期完成的。

程式在執行時與函式庫再無瓜葛,移植方便。

linux下靜態庫的名字一般是lib***.a。其中***是該庫的名字,字尾是.a

# gcc -c hello.c -o hello.o
然後檢視一下果然多了乙個hello.o檔案:

# ls

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

ar -cr libhel.a hello.o
引數解析:

-c:表示建立

-r: 表示replace,如果存在則用新生成的進行替換。

再檢視目錄的話就會多出來乙個名為libhel.a的檔案,這個就是生成的靜態庫。

# ls

hello.c hello.h hello.o libhel.a main.c

在使用靜態庫之前還是來熟悉一下幾個gcc的選項引數:

-l:-l選項指定額外的函式庫的搜尋路徑,如果不指定的話,則只會搜尋gcc的預設路徑,比如有:/usr/lib等,不會搜尋到我們剛才建立的靜態庫。

-l:-l選項是指在連線時候指定連線的函式庫名字。比如這裡就是函式庫名 :-lhel

注意:-l 後面不需要完成的名字,而是去掉了前面的lib字首以及.a字尾名。

# gcc main.c -l. -lhel -o execuate
至此那個可執行檔案:

./execuate

hello!

動態庫的建立和使用和上面的靜態庫使用差不多,只不過個別的命令的變化.

由目標檔案.o生成動態庫:

# gcc -shared -fpic -o libmyhello.so hello.o
然後就會生成libmyhello.so動態庫。在這李我們可以看出乙個區別就是建立動態庫不需要ar等打包工具,直接由gcc編譯器就可建立。

2. 使用動態庫

使用的命令和使用靜態庫是一樣的:

# gcc main.c -l. -lmyhello -o hhh
上述命令生成可執行檔案hhh

執行生成的可執行檔案

./hhh

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

錯誤提示,找不到動態庫檔案libmyhello.so。程式在執行時,會查詢需要的動態庫檔案。若找到,則載入動態庫,否則將提示類似上述錯誤而終止程式執行。有多種方法可以解決。

最簡單的就是將檔案libmyhello.so複製到目錄/usr/lib中,因為/usr/libgcc編譯器查詢庫的預設路徑之一:

$ sudo

cp libmyhello.so /usr/lib

然後執行:

./hhh

hello!

參考資料:

每天進步一點點!

2020/8/09   成都

linux 下靜態庫和動態庫

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

linux下的靜態庫和動態庫

庫是什麼?在我們實際程式設計中,經常會引入各種庫函式,那麼庫是什麼?從本質上來說是一種可執行 的二進位制格式,可以被載入記憶體中執行。庫分靜態庫和動態庫兩種。靜態庫 linux下靜態庫的名字一般是lib a,為庫的名字。利用靜態函式庫編譯成的檔案比較大,因為整個函式庫的所有資料都會被整合進目標 中,...

linux下的靜態庫和動態庫

意義 為了避免 的重寫率,我們可以將已經寫好的 形成乙個庫,當我們再次用到的時候可以直接呼叫,而不是重新去寫,即 站在巨人的肩膀上 linux下有兩種庫 一 靜態庫 準備工作 int swap int x,int y include int main 1 將我們需要的函式生成乙個.o 檔案 root...