靜態庫的用法
靜態庫的文件名 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了。
靜態庫和動態庫的特點:
- 靜態庫:
- 編譯的時候,直接把靜態庫的代碼直接編譯到目標文件
- 執行速度快,不需要在執行的時候加載動態庫
- 庫文件修改后,必須重新編譯使用庫的代碼
- 動態庫
- 編譯的時候,不把靜態庫的代碼直接編譯到目標文件
- 執行速度慢,在執行的時候需要加載動態庫
- 庫文件修改后,一般不需要重新編譯使用庫的代碼,只有在庫的接口改變時,才需要重新編譯使用庫的代碼。