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了。

靜態庫和動態庫的特點:

  • 靜態庫:
    • 編譯的時候,直接把靜態庫的代碼直接編譯到目標文件
    • 執行速度快,不需要在執行的時候加載動態庫
    • 庫文件修改后,必須重新編譯使用庫的代碼
  • 動態庫
    • 編譯的時候,不把靜態庫的代碼直接編譯到目標文件
    • 執行速度慢,在執行的時候需要加載動態庫
    • 庫文件修改后,一般不需要重新編譯使用庫的代碼,只有在庫的接口改變時,才需要重新編譯使用庫的代碼。

c/c++ 學習互助QQ群:877684253

本人微信:xiaoshitou5854


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM