1(1)庫文件:靜態庫文件 和 共用庫文件(2)比較a.靜態庫文件: 使用靜態庫文件時,直接把代碼/指令複製到目標文件中 目標文件會顯得比較龐大,修改和維護都不方便 可以脫離靜態庫文件,效率比較高 b.共用庫文件: 使用共用庫時,將代碼/指令所對應的地址複製到目標文件 目標文件會比較小,修改和維護比 ...
1(1)庫文件:靜態庫文件 和 共用庫文件
(2)比較
a.靜態庫文件:
使用靜態庫文件時,直接把代碼/指令複製到目標文件中
目標文件會顯得比較龐大,修改和維護都不方便
可以脫離靜態庫文件,效率比較高
b.共用庫文件:
使用共用庫時,將代碼/指令所對應的地址複製到目標文件
目標文件會比較小,修改和維護比較方便
不可以脫離共用庫文件,效率比較低
(3)基本命令
ldd a.out => 查看文件a.out所依賴的庫文件
gcc/cc -static xxx.c => 要求按照靜態庫方式編譯鏈接,得到的可執行文件會比較大
2 靜態庫文件的生成和使用
(1)靜態庫文件的生成步驟
a.編寫源代碼xxx.c,如:vi adder.c
b.只編譯不鏈接生成.o的目標文件
gcc/cc -c adder.c
c.使用命令ar -r/*插入*/ lib庫名.a xxx.o 生成靜態庫
ar -r libadder.a adder.o
註意:
a.lib庫名.a 叫做靜態庫文件名,與庫名不同,註意區分
b.靜態庫文件的命名規則一般為lib開頭,.a為尾碼,中間的庫名自定義即可
(2)靜態庫文件的使用步驟
a.編寫源程式xxx.c,如:vi main.c
b.只編譯不鏈接,生成目標文件.o
如: cc -c main.c
c.連接目標文件和靜態庫文件
1)直接連接
cc main.o libadder.a
2)通過選項進行連接(掌握)
cc main.o -l 庫名 -L 庫文件所在的路徑
cc main.o -l adder -L .
3)配置環境變數LIBARARY_PATH
export LIBRARY_PATH=$LIBRARY_PATH:.
cc main.o -l adder
3.3 共用庫的生成和使用步驟
(1)共用庫的生成步驟
a.編寫源程式xxx.c,如 vi adder.c
b.只編譯不鏈接生成.o目標文件
gcc/cc -c -fpic/*小模式*/ adder.c
c.使用編譯選項生成共用庫文件
gcc/cc -shared/*共用*/ adder.o -o lib庫名.so
(2)共用庫的使用步驟
a.編寫測試程式xxx.c,如 vi main.c
b.只編譯不鏈接生成.o目標文件
如: cc -c main.c
c.連接測試文件和共用庫文件
1)直接連接
cc main.o libadder.so
2)使用編譯選項進行連接(掌握)
cc main.o -l adder -L .
3)配置環境變數LIBRARY_PATH
export LIBRARY_PATH=$LIBRARY_PATH:.
cc main.o -l adder
註意:
對於共用庫文件的使用來說,要求配置LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
共用庫的動態載入
(1)dlopen函數
#include <dlfcn.h>
void *dlopen(const char *filename, int flag);
第一個參數:字元串形式的文件名
第二個參數:載入標誌
RTLD_LAZY - 延遲載入
RTLD_NOW - 立即載入
返回值:返回共用庫文件的句柄/地址
函數功能:打開和載入共用庫文件,根據返回值來可以
操作該共用庫文件
(2)dlerror函數
char *dlerror(void);
函數功能:
主要用於獲取dlopen()/dlsym()/dlclose()/函數調用期間發生的最新錯誤信息,
通過返回值返回,返回NULL則沒有錯誤
(3)dlsym函數
void *dlsym(void *handle, const char *symbol);
第一個參數:dlopen函數的返回值
第二個參數:標識,一般用於查找具體的函數名
返回值:返回標識在記憶體中的地址
函數功能:
根據handle在對應的共用庫中查找名字為symbol標識的地址
(4)dlclose函數
int dlclose(void *handle);
函數功能:
表示關閉handle所對應的共用庫文件
註意:
連接的時候需要指定選項: -ldl
動態庫使用示例:
//加法計算的頭文件 #ifndef ADDER_H #define ADDER_H //計算兩個int類型參數的和 int add_int(int ia,int ib); //計算兩個double類型參數的和 double add_double(double da,double db); #endif
//加法計算的源文件 #include "adder.h" //#include "../adder.h" //計算兩個int類型參數的和 int add_int(int ia,int ib) { return ia + ib; } //計算兩個double類型參數的和 double add_double(double da,double db) { return da + db; }
//共用庫的動態載入 #include <stdio.h> #include <dlfcn.h> int main(void) { //1.打開和載入共用庫文件 void* handler = dlopen("./shared/libadder.so",RTLD_NOW); //2.判斷是否出錯 char* error = dlerror(); if(error != NULL) { printf("載入共用庫文件失敗\n"); return -1; } //3.尋找共用庫中指定的標識 int (*add_pint)(int ia,int ib); add_pint = dlsym(handler,"add_int"); //4.判斷是否出錯 error = dlerror(); if(error != NULL) { printf("獲取標識失敗\n"); return -1; } //5.使用標識進行處理 printf("計算的結果是:%d\n",add_pint(10,20));//30 //6.關閉共用庫文件 dlclose(handler); return 0; }