深入探討Linux靜態庫與動態庫的詳解(轉)
2.生成動態庫並使用
linux下編譯時通過 -shared 參數可以生成動態庫(.so)文件,如下
庫從本質上來說是一種可執行代碼的二進制格式,可以被載入內存中執行。庫分靜態庫和動態庫兩種。
一、靜態庫和動態庫的區別
1. 靜態函數庫
這類庫的名字一般是libxxx.a;利用靜態函數庫編譯成的文件比較大--空間,因為整個函數庫的所有數據都會被整合進目標代碼中,他的優點就顯而易見了,即編譯後的執行程序不需要外部的函數庫支持,因為所有使用的函數都已經被編譯進去了。當然這也會成為他的缺點,因為如果靜態函數庫改變了,那麽你的程序必須重新編譯。
2. 動態函數庫
這類庫的名字一般是libxxx.so;相對於靜態函數庫,動態函數庫在編譯的時候並沒有被編譯
二、靜態庫
(一)簡單介紹
gcc main.c src/* -I./include -L./lib -lmpi -o main
main.c 為主函數
src/* 為源文件
-I後面接頭文件
-L後面接庫文件路徑路徑
-l後面接庫文件名,全名為libmpi.a
.a為靜態庫
(二)編寫及使用靜態庫
(1)設計庫源碼 pr1.c、pr2.c 和 main.c 代碼如下:
[[email protected] make_lib]$ cat pr1.c #include <stdio.h> void print1(void) { printf("This is the first lib src!\n"); } [[email protected] make_lib]$ cat pr2.c #include<stdio.h> void print2(void) { printf("This is the second src lib!\n"); } [[email protected] make_lib]$ cat main.c int main(void) { print1(); print2(); return 0; }
(2) 編譯pr1.c、pr2.c 文件
[[email protected] make_lib]$ gcc -O -c pr1.c pr2.c [[email protected] make_lib]$ ls -l pr*.o -rw-rw-r-- 1 bill bill 804 4 月 15 11:11 pr1.o -rw-rw-r-- 1 bill bill 804 4 月 15 11:11 pr2.o
(3) 鏈接靜態庫
為了在編譯程序中正確找到庫文件,靜態庫必須按照 lib[name].a 的規則命名,如下例中[name]=pr.
ar參數意義:
r:在庫中插入模塊(替換)。當插入的模塊名已經在庫中存在,則替換同名的模塊。
s:寫入一個目標文件索引到庫中,或者更新一個存在的目標文件索引。
v:該選項用來顯示執行操作選項的附加信息。
t:顯示庫的模塊表清單。一般只顯示模塊名。
[[email protected] make_lib]$ ar -rsv libpr.a pr1.o pr2.o a - pr1.o a - pr2.o [[email protected] make_lib]$ ar -t libpr.a pr1.o pr2.o
(4) 編譯鏈接選項
-L 及-l 參數放在後面.其中,-L 加載庫文件路徑,-l 指明庫文件名字.
[[email protected] make_lib]$ gcc -o main main.c -L./ -lpr //生成main
(5)執行目標程序
[[email protected] make_lib]$ ./main This is the first lib src! This is the second src lib!
三、動態庫(隱式調用)
(1)設計庫代碼
[[email protected] make_lib]$ cat pr1.c #include <stdio.h> int p = 2; void print(){ printf("%p:%d\n", &p, p); printf("This is the first dll src!\n"); }
(2)生成動態庫 xxx.so
[[email protected] make_lib]$ gcc -O -fpic -shared -o xxx.so pr1.c [[email protected] make_lib]$ ls -l *.so -rwxrwxr-x 1 bill bill 6592 4 月 15 15:19 xxx.so
(3)動態庫的隱式調用
[[email protected] make_lib]$ cat main.c int main() { print(); return 0; } [[email protected] make_lib]$ gcc -o main main.c ./xxx.so [[email protected] make_lib]$ ./main 0x97b5d4:2 this is the first lib src!
當動態庫的位置發生改變時, 程序將無法正常運行; 而動態庫取代靜態庫的好處之一則是通過更新動態庫而隨時升級庫的內容.
示例:
首先是準備工作,把我們需要封裝成庫文件的函數的頭文件與源文件寫好,如下:
1 //myAPI.h 2 int ADD(int a, int b); 3 int MINUS(int a, int b);
1 //myAPI.cpp 2 #include "myAPI.h" 3 4 int ADD(int a, int b){ 5 return a + b; 6 } 7 8 int MINUS(int a, int b){ 9 return a - b; 10 }
接下來準備一個測試用的主函數源文件:
1 //main.cpp 2 #include "myAPI.h" 3 #include <iostream> 4 5 int main(){ 6 std::cout << "1 + 1 = " << ADD(1, 1) << std::endl; 7 std::cout << "1 - 1 = " << MINUS(1, 1) << std::endl; 8 return 0; 9 }
最後,先編譯我們的 myAPI.cpp 文件生成 myAPI.o 目標文件
g++ -c myAPI.cpp
1.生成靜態庫並使用
linux下用生成靜態庫的命令 ar 處理 myAPI.o 文件生成靜態庫文件,生成的庫文件應遵循規範,及linux下庫文件加“lib”前綴。所以針對本例,通過如下一條命令即可生成 libmyAPI.a 靜態庫:
ar crv libmyAPI.a myAPI.o
接下來即可在項目編譯過程中利用靜態庫了,此時 myAPI.cpp 這個庫函數的定義文件已經不需要了。main.cpp 編譯命令如下(註意,依賴的靜態庫文件要放在被依賴項後面):
g++ main.cpp libmyAPI.a -o output
編譯通過後即可運行可執行文件 output , 此時 libmyAPI.a 也已經是不需要的了。執行命令並輸出結果如下:
./output
2.生成動態庫並使用
linux下編譯時通過 -shared 參數可以生成動態庫(.so)文件,如下
g++ -shared -fPIC -o libmyAPI.so myAPI.cpp
生成的動態庫在編譯時需要聲明,運行時需要被依賴。聲明如下
g++ main.cpp -L. -o output ./libmyAPI.so
”-L.”標記告訴G++函數庫可能位於當前目錄;使用”-lmyAPI”標記來告訴G++驅動程序在連接階段引用共享函數庫libmyAPI.so。
使用時如果提示如下錯誤,則將 libmyAPI.so 移到 /usr/lib 目錄下即可:
./output
轉自:http://blog.csdn.net/u013256622/article/details/51811072
http://www.jb51.net/article/37409.htm
深入探討Linux靜態庫與動態庫的詳解(轉)