動態庫和靜態庫

2022-05-01 14:54:13 字數 3016 閱讀 8041

前言

在linux系統下開發應用的時候我們常會用到一些已有的介面,這些介面一般是以庫的形式提供給我們使用的,常見的形式有兩種,一種以.a為字尾的靜態庫;一種是以.so為字尾的動態庫。

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

1.靜態庫

假設有乙個列印「hello world!」的功能的庫,我們要在main函式中呼叫這個庫中的列印介面。下面我們以靜態庫的形式來實現。

1.1.建立靜態庫

首先,我們有乙個列印「hello world!」的原始檔

ydq@docsis4 gcc $ cat hello.c

#include "hello.h"

#include

void hello(void)

接著我們用這個原始檔來生成乙個靜態庫,首先我們必須把原始檔hello.c編譯為目標檔案hello.o。

ydq@docsis4 gcc $ gcc -c hello.c

ydq@docsis4 gcc $ ls

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

然後我們把目標檔案歸檔

ydq@docsis4 gcc $ ar -r libhello.a hello.o

ar: creating libhello.a

ydq@docsis4 gcc $ ls

hello.c hello.h hello.o libhello.a*

1.2.鏈結靜態庫

我們用gcc編譯時鏈結靜態庫,編譯完成後,執行以下生成的可執行檔案

ydq@docsis4 gcc $ gcc main.c libhello.a -o main.static

ydq@docsis4 gcc $ ./main.static

hello world

這樣,我們就實現了用靜態庫的方式為我們的程式main.c提供乙個列印hello world語言的函式介面了。

ps: 程式 ar 配合引數 -r 建立乙個新庫 libhello.a 並將命令列中列出的物件檔案插入。採用這種方法,如果庫不存在的話,引數 -r 將建立乙個新的庫,而如果庫存在的話,將用新的模組替換原來的模組。

2.動態庫

在這裡,我們用動態庫的形式實現列印"hello world!"的函式介面。

2.1.建立動態庫

我們照常用hello.c來編譯生成動態庫,執行以下命令就可以生成乙個動態庫。

ydq@docsis4 gcc $ gcc -fpic -shared hello.c -o libhello.so

我們檢視一下當前目錄,發現多了乙個libhello.so檔案

ydq@docsis4 gcc $ ls

hello.c hello.h libhello.so* main.c

2.2 動態庫的使用

首先,我們編寫乙個main.c原始檔。

ydq@docsis4 gcc $ cat main.c

#include "hello.h"

#include

int main(void)

ydq@docsis4 gcc $

好了,我們已經有了呼叫hello()介面的main函式了,這時候可能部分同學就有疑問了,哎我們是怎麼知道這個hello()函式是怎麼使用的呢?嗯,這個是好問題。一般情況下我們可以通過對應的標頭檔案來檢視到這個函式的原型,有了原型,我們就知道咋傳參使用啦。下面就是對應的標頭檔案。

ydq@docsis4 gcc $ cat hello.h

#ifndef __hello_h_

#define __hello_h_

extern void hello(void);

#endif

好的,現在我們已經知道怎麼使用hello()函式和編寫了乙個呼叫hello函式的main.c原始檔,接下來我們就來編譯可執行檔案啦,編譯很簡單,我們只需要在gcc編譯時加上-lhello選項就可以鏈結上動態庫了,好讓我們來嘗試一下。

ydq@docsis4 gcc $ gcc main.c -o main -lhello

/usr/bin/ld: cannot find -lhello

collect2: error: ld returned 1 exit status

我去,咋回事?怎麼提示說不能夠找到hello這個庫?莫非命令敲錯了?其實沒有指定動態庫的路徑拉,一般情況下系統只認/usr/lib這個目錄是動態庫的目錄,所以編譯器在鏈結的時候會預設去/usr/lib目錄上找,在/usr/lib目錄裡當然沒有你的libhello.so庫啦。聽到我這樣說,肯定有很多小機靈鬼知道咋解決了,我直接把libhello.so給拷貝到/usr/lib目錄下不就行了嗎?嗯,這個確實可以解決問題,不過,我們還可以加-l./來指定鏈結的時候在當前工作目錄下尋找libhello.so。好,我們再試一下。

ydq@docsis4 gcc $ gcc main.c -o main -lhello -l./

編譯成功了,這時候我們在當前目錄下有了main這個可執行檔案,好傢伙,讓我們執行試試。

ydq@docsis4 gcc $ ./main

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

哦,這個是咋回事?執行的時候又找不到這個動態庫了?怎麼解決呢?莫非也可以把libhello.so拷貝到/usr/lib上去就可以解決了?答案是不行的拉,除非是在鏈結前就把libhello.so放到/usr/lib目錄中,這樣在main執行的時候,才不會提示說找不到該庫。那有沒有解決方法呢?肯定啦,不然還怎麼玩。

總結

到了這裡,我們已經講明白了動態庫和靜態庫的建立和使用過程,下一章節我們會講動態庫和靜態庫的區別,以及選擇使用靜態庫還是使用動態庫的理由。

動態庫和靜態庫

本文主要解決以下幾個問題 1 為什麼要使用庫?2 庫的分類 3 建立自己的庫 或許大家對自己初學linux時的情形仍記憶尤新吧。如果沒有乙個能較好的解決依賴關係的包管理器,在linux下安裝軟體將是一件及其痛苦的工作。你裝a包時,可能會提示你要先裝b包,當你費盡心力找到b包時,可能又會提示你要先安裝...

動態庫和靜態庫

先抄一段 windows下的動態庫和靜態庫區別解釋,其實linux下意義一樣的,不過字尾名有些區別 靜態庫 在編譯的時候載入生成目標檔案,在執行時不用載入庫,在執行時對庫沒有依賴性。動態庫 在目標檔案執行時載入,手動載入,且對庫有依賴性。兩者區別 一,靜態庫的使用需要 1 包含乙個對應的標頭檔案告知...

動態庫和靜態庫

簡單的說,使用動態庫就是在鏈結的時候,不會將動態庫的 鏈結到可執行檔案中,而是採用symbol的方式。使用靜態庫,生成可執行檔案的時候,會將靜態庫的 鏈結到可執行檔案中。這樣,動態庫體積會很小,並且可以,依賴於更新的動態庫,但是,缺點是不穩定。靜態庫會更加穩定,但是體積會很大。靜態庫 就是多個目標檔...