Linux下動態庫和靜態庫制作與調用
1.動態庫和靜態庫簡介
靜態庫是指在應用中,有一些公共代碼需要反復使用,就把這些代碼編譯為“庫”文件;在鏈接步驟中,連接器將從庫文件取得所需的代碼,復制到生成的可執行文件中。這種庫稱為其特點是可執行文件中包含了庫代碼的一份完整拷貝;缺點就是被多次使用就會有多份冗余拷貝。
動態庫又稱動態鏈接庫英文為DLL,是指DynamicLinkLibrary 的縮寫形式,DLL是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬于其可執行代碼的函數
靜態庫:在編譯的時候加載生成目標文件,在運行時不用加載庫,在運行時對庫沒有依賴性。
動態庫:在目標文件運行時加載,對庫有依賴性。
?1.1 Linux下動態庫和靜態庫命令方式
??動態庫命名方式:libxxx.so。其中so是shared objecd的縮寫,即可以共享的目標文件,lib為庫的固定格式,xxx為庫名稱,.so為動態庫后綴。
??動態庫命名方式:libxxx.a xxx靜態庫名稱。Linux 上的靜態庫,其實是目標文件的歸檔文件。
?1.2 編譯生成共享庫示例
?命令:gcc -fPIC -shared -o libxxx.so xxx.c
此過程分為編譯和鏈接兩部分,-fPIC是編譯選項,PIC表示要生成位置無關的代碼,這是動態庫的特性,-shared是鏈接選項,告訴gcc生成動態庫而不是可執行文件。
上述命令等同于:
gcc -fPIC -c xxx.c
gcc -shared -o libxxx.so xxx.o
如下代碼為例實現動態庫編譯與調用:
[wbyq@wbyq shared]$ gcc -fPIC -shared -o libmyfile.so ./src/*.c -I./include
??gcc -I ?指定頭文路徑
?1.3 動態庫調用
[wbyq@wbyq shared]$ gcc main.c -Iinclude -lmyfile -L./lib
??gcc -L ?指定動態庫路徑
??gcc -l ?指定動態庫名字
?1.4 程序運行
[wbyq@wbyq shared]$ ./a.out
./a.out: error while loading shared libraries: libmyfile.so: cannot open shared object file: No such file or directory
??錯誤原因:
??系統動態庫默認搜索路徑: /lib 和 /usr/lib
??解決辦法1:將libmyfile.so 拷貝到/usr/lib或者/lib目錄下。
??解決辦法2:修改系統環境變量,動態庫環境變量:LD_LIBRARY_PATH
??修改環境變量示例:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/hgfs/ubuntu/shared/lib
??注意:在命令行修改環境變量只對當前終端有效。
??解決辦法2:修改系統啟動文件
??Ubuntu下開機普通用戶啟動文件:~/.bashrc ~/.profile
??管理員用戶:/.profile
??修改~/.bashrc文件:
??同步文件:source ~/.bashrc
2 linux靜態庫創建與調用
?2.1 linux靜態庫的命令規則
??靜態庫libxxx.a ? xxx靜態庫名稱。Linux 上的靜態庫,其實是目標文件的歸檔文件。
?2.2 linux靜態庫創建步驟
??(1)編寫源文件,通過gcc -c生成目標文件。
??(2)用ar歸檔目標文件,生成靜態庫。
??(3)配合靜態庫,寫一個使用靜態庫中函數的頭文件。
??(4).使用靜態庫時,在源碼中包含對應頭文件,鏈接是記得鏈接自己的庫。
?2.3 生成靜態庫
[wbyq@wbyq shared]$ ar t ./lib/libmyfile2.a #查看靜態庫信息
my_cat.o
my_cp.o
my_du.o
[wbyq@wbyq shared]$ gcc main.c -L./lib -lmyfile2 -o app -Iinclude #調用靜態
3.gcc編譯器常用選項
?3.1 gcc基本用法
??使用 gcc編譯器的時候,我們必須給出一系列必要的調用參數和文件名稱。 GCC 編譯器的調用參數大約有100 多個,這里只介紹其中最基本、最常用的參數。
??gcc 最基本用法:gcc [參數] [文件名稱]
3.2 常用參數
-c 只編譯:不鏈接成為可執行文件,編譯器只是由輸入的.c 等源代碼文件生成.o 為后綴的目標文件,通常用于編譯不包含主程序的子程序文件。
-o output_filename:確定輸出文件的名稱為 output_filename,同時這個名稱不能和源文件同名。如果不給出這個選項, gcc 就給出預設的可執行文件 a.out。
-g:產生符號調試工具(GNU 的 gdb)所必要的符號信息,要想對源代碼進行調試,我們就必須加入這個選項。
-O:對程序進行優化編譯、鏈接,采用這個選項,整個源代碼會在編譯、鏈接過程中進行優化處理,這樣產生的可執行文件的執行效率可以提高,但是,編譯、鏈接的速度就相應地要慢一些。
-O2:比-O 更好的優化編譯、鏈接,當然整個編譯、鏈接過程會更慢。
-E:僅執行編譯預處理;
-S:將 C 代碼轉換為匯編代碼;
3.3 編譯時指定庫文件和頭文件路徑
-L:指定動態庫路徑(可以指定多個路徑)。
示例: gcc test.c -o app -L/usr/lib -L ./lib
?-I:指定頭文件存放的路徑(可以指定多個路徑)。
示例: gcc test.c -I ./ -I /include
?-l:指定庫名稱(可以指定多個路徑)。
示例: gcc test.c -l my_test -l func
4.linux下采用dlopen調用動態庫
4.1 dlopen調用動態庫意義
為了使程序方便擴展,具備通用性,可以采用插件形式。采用異步事件驅動模型,保證主程序邏輯不變,將各個業務已動態鏈接庫的形式加載進來,這就是所謂的插件。 linux 提供了加載和處理動態鏈接庫的系統調用,非常方便。
生成動態庫:gcc -fPIC -shared libxxx.so -o xxx.c
?4.2 dlopen系列函數介紹
#include
void *dlopen(const char *filename, int flags);
函數功能:打開動態庫
形參:filename --動態庫路徑+名字 例:./lib/libmyfile.so
???flags --RTLD_LAZY使用時解析(暫緩解析)
???RTLD_NOW --立刻解析
返回值: handle --成功返回庫引用信息,失敗返回NULL
int dlclose(void *handle);
函數功能:關閉動態庫
形參:handle --dlopen函數返回值
void *dlsym(void handle, const charsymbol);
函數功能:符號解析
形參:handle --dlopen函數返回值
???symbol --要解析的符號
返回值:成功返回符號地址,
????失敗返回NULL
char *dlerror(void); //打印錯誤信息
?4.3函數解析示例
#include "./include/my_file.h"
#include
#include
int main()
{
int (*p)(const char *);//定義一個函數指針
/*打開動態庫*/
void *handle=dlopen("./lib/libmyfile.so",RTLD_LAZY);
if(handle==NULL)
{
printf("動態庫解析失敗%s\n",dlerror());//打印錯誤信息
return 0;
}
/*符號解析*/
p=dlsym(handle,"my_cat");
int res=p("main.c");
printf("res=%d\n",res);
p=dlsym(handle,"my_du");
p("main.c");
//typedef unsigned int u32;
typedef int (*my_cp)(const char *,const char *);//my_cp表示函數指針類型
my_cp test;//定義函數指針變量
test=dlsym(handle,"my_cp");
test("main.c","test.c");
dlclose(handle);//關閉動態庫
}
?4.4變量解析示例
#include "./include/my_file.h"
#include
#include
int main()
{
int (*p)(const char *);//定義一個函數指針
/*打開動態庫*/
void *handle=dlopen("./lib/libmyfile.so",RTLD_LAZY);
if(handle==NULL)
{
printf("動態庫解析失敗%s\n",dlerror());//打印錯誤信息
return 0;
}
/*符號解析*/
p=dlsym(handle,"my_du");
p("main.c");
printf("-----------------------------------\n");
/*解析變量*/
int *p2;
p2=dlsym(handle,"data");
printf("*p2=%d\n",*p2);
*p2=300;
p("main.c");
dlclose(handle);//關閉動態庫
}
審核編輯:湯梓紅
-
Linux
+關注
關注
87文章
11292瀏覽量
209323 -
靜態庫
+關注
關注
0文章
21瀏覽量
7426 -
動態庫
+關注
關注
0文章
17瀏覽量
6222
發布評論請先 登錄
相關推薦
評論