C/C++ 動態庫與靜態庫的製作和使用
靜態庫的用法
靜態庫的檔名 libxxx.a -->對應Windows的.lib檔案
做靜態庫的命令:
ar rcs libxxx.a file1.o file2.o file.o
使用靜態庫:
gcc main.c -L lib/ -lxxx
注意:-L的作用是告訴gcc你的libxxx.a放在了哪個目錄裡;-l的作用是告訴gcc使用哪個靜態庫。
舉個例子,目錄結果如下:
├── include │└── head.h ├── lib │ ├── main.c └── src ├── add.c ├── mul.c └── sub.c
head.h
int add(int, int); int sub(int, int); int mul(int, int);
add.c
int add(int a, int b){ return a + b; }
sub.c
int sub(int a, int b){ return a - b; }
mul.c
int mul(int a, int b){ return a * b; }
- 步驟1:在src目錄執行下面的命令,生產.o檔案
gcc -c *.c
執行後,在src目錄下生產了add.o,sub.o,mul.o三個檔案
- 步驟2:在src目錄執行下面的命令,生產libCalc.a檔案
ar rcs libCalc.a *.o
執行後,在src目錄下生產了libCalc.a
- 步驟3:在src目錄執行下面的命令,把libCalc.a移動到上層的lib資料夾
mv libCalc.a ../lib/
執行後,在lib資料夾出現了libCalc.a
main.c
#include <stdio.h> #include "head.h" int main(){ int a = 10, b = 5; printf("add:%d\n",add(a, b)); printf("sub:%d\n",sub(a, b)); printf("mul:%d\n",mul(a, b)); }
- 步驟4:在src的上層目錄,執行下面命令生產a.out檔案
gcc main.c -I include/ -L lib/ -lCalc
-
-I:指定標頭檔案所在的路徑
- -L:指定靜態庫檔案所在的路徑
-
-l:指定使用哪個靜態庫
最後目錄結構如下:
├── a.out ├── include │└── head.h ├── lib │└── libCalc.a ├── main.c └── src ├── add.c ├── add.o ├── mul.c ├── mul.o ├── sub.c └── sub.o
動態庫的用法
動態庫的檔名 libxxx.so -->對應windows的.dll檔案
編譯時,需要加【-fPIC】選項。
它的作用是,編譯出與位置無關的程式碼。因為動態庫在載入到下圖的共享庫區的時候,不一定載入到哪個位置,
所以加了-fPIC後,就記錄了每個函式相對於這個動態庫頭地址的偏移,載入後動態庫在記憶體裡的頭地址是知道的,又知道了每個函式相對於頭的偏移量,自然而然地就能夠找到每個函式在記憶體裡的位置了。
做靜態庫的命令(-shared):
gcc -shared -o libCalc.so *.o
用【ldd】命令檢視編譯出來的可執行檔案檔案
ldd a.out
結果如下:
ys@ys-VirtualBox:~/lianxi1$ ldd a.out linux-vdso.so.1 (0x00007ffdebd2d000) libCalc.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3b3e7ee000) /lib64/ld-linux-x86-64.so.2 (0x00007f3b3ede1000)
發現【libCalc.so => not found】
解決辦法1:把做好的動態庫libCalc.so拷貝到【/lib】或者【/usr/lib】下,也可以用ln做軟硬連線:把當前目錄下的lib目錄下的libCalc.so連結到/lib下
sudo ln -s ./lib/libCalc.so /lib/
結果如下:
發現軟連線是紅色的,也就是不能使用的意思,錯誤在於./lib/libCalc.so這個路徑是不存在的,原因在於上面的命令使用的是相對路徑,改成絕對路徑就OK了,命令如下:
sudo ln -s ~/lianxi1/lib/libCalc.so /lib/
結果如下:
發現軟連線是綠色的了,說明庫可以使用了,開森啊。
再用【ldd】命令檢視編譯出來的可執行檔案檔案
ldd a.out
結果如下:
ys@ys-VirtualBox:~/lianxi1$ ldd a.out linux-vdso.so.1 (0x00007ffe783c4000) libCalc.so => /lib/libCalc.so (0x00007f35fd6ae000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f35fd2bd000) /lib64/ld-linux-x86-64.so.2 (0x00007f35fdab2000)
發現【libCalc.so】已經被找到了,好開心。
但是這種方法不推薦使用。理由是,放在了系統的動態庫目錄裡,容易和別的庫重複,發生衝突。
解決辦法2:告訴系統,給我加一個動態庫的路徑,這個是最好的辦法。
- 首先編輯/etc/ld.so.conf檔案,新增你自己的庫的路徑
- 然後,執行:【sudo ldconfig】,就OK了。
靜態庫和動態庫的特點:
- 靜態庫:
- 編譯的時候,直接把靜態庫的程式碼直接編譯到目標檔案
- 執行速度快,不需要在執行的時候載入動態庫
- 庫檔案修改後,必須重新編譯使用庫的程式碼
- 動態庫
- 編譯的時候,不把靜態庫的程式碼直接編譯到目標檔案
- 執行速度慢,在執行的時候需要載入動態庫
- 庫檔案修改後,一般不需要重新編譯使用庫的程式碼,只有在庫的介面改變時,才需要重新編譯使用庫的程式碼。
Linux公社的RSS地址 : https://www.linuxidc.com/rssFeed.aspx
本文永久更新連結地址: https://www.linuxidc.com/Linux/2019-04/158302.htm