庫即二進制形式的目標模塊,使用庫可以很方便對程序進行模塊化設計,
方便對某些固定功能的重複使用,方便對某些功能進行更新。
庫與.c文件關係如下圖:
庫分爲兩種類型,即靜態庫和動態庫;
靜態庫擴展名.a ,庫中封裝的二進制代碼,在鏈接階段被複制到調用模塊中,
調用模塊運行時不再需要靜態庫的支持;
動態庫擴展名.so ,庫中封裝的二進制代碼,在鏈接階段不會複製到調用模塊,
被嵌入到調用模塊中的僅僅是被調用函數在庫中的相對地址,
因此,調用模塊在運行時需要動態庫的支持。
動態庫和靜態庫相比,使用更爲靈活,更常見。
庫的製作:
靜態庫的製作:
第一步:編輯源程序,包括a.c a.h . . .
第二步:源程序編譯成目標文件,gcc -c a.c --->a.o . . .
第三步:打包目標文件,即把他們做成庫,ar -r libxxx.a a.o b.o c.o . . .
ar命令解釋:
格式:ar [選項] 靜態庫名 目標文件列表
選項如下:
-r:將目標文件插入到靜態庫,若目標文件已存在,則更新
-q:將目標文件追加到靜態庫的末尾
-d:從靜態庫中刪除指定的目標文件
-t:列表形式顯示靜態庫中的目標文件
-x:將靜態庫展開爲目標文件
動態庫的製作:
第一步:編輯源程序,包括xxx.c xxx.h
第二步:編譯成目標模塊,gcc -fpic -c a.c . . .
-fpic:小模式,代碼量小,速度快,只支持一部分平臺,比如Linux
-fPIC:大模式,代碼量較大,速度較慢,支持所有平臺
第三步:鏈接成庫,gcc -shared a.o . . . -o libxxx.so
庫的使用:
1、直接調用法
gcc main.c libmath.a / gcc main.c libmath.so
2、參數調用法
gcc main.c -lmath -L. //-l庫名 -L庫所在路徑
3、設置環境變量法
靜態庫設置方法:export LIBRARY_PATH=$LIBRARY_PATH:.
動態庫設置方法:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
爲了永久設置環境變量,可將上述語句寫入~/.bashrc
gcc main.c -lmath
動態庫的使用還可以利用Linux中的dl庫實現動態加載
簡單實例如下:
其中add和show是庫中的函數,add 的功能是將兩個數相加,返回結果;show 的功能是 printf 傳進來的數
#include <stdio.h>
#include <dlfcn.h>
#include "math.h" //動態庫裏的頭文件
#include "show.h" //動態庫裏的頭文件
typedef int (*operation)(int,int); //給函數類型 int (*) (int,int) 起別名operation
typedef void (*d_show)(int);
int main()
{
int a,b;
void *handle = dlopen("./libmath.so",RTLD_LAZY); //獲取庫的句柄
if(handle == NULL)
{
printf("%s\n",dlerror());
return;
}
operation add = (operation)dlsym(handle,"add"); //“add”爲庫裏面的函數,執行加法運算,該語句的作用是獲取add函數在庫裏面的地址
if(add == NULL)
{
printf("%s\n",dlerror());
return;
}
d_show show = (d_show)dlsym(handle,"show");
if(show == NULL)
{
printf("%s\n",dlerror());
return;
}
printf("請輸入兩個整數:");
scanf("%d %d",&a,&b);
printf("%d + %d = ",a,b);
show(add(a,b)); //show,add爲本文件的變量,不是庫裏面的函數名
dlclose(handle);
return 0;
}