一前言.
在windows下,靜態鏈接庫文件后綴是.lib, 動態鏈接庫文件后綴是.dll
在linux下,靜態鏈接庫文件后綴是.a, 動態鏈接庫文件后綴是.so
二.linux下的靜態鏈接庫(暫不說windows下的dll)
1.新建一個printf.c 和 printf.h文件,在printf.c文件寫上相應的測試函數,以及在.h文件中聲明。
2.新建一個makefile文件,在makefile中寫:
all:
gcc printf.c -o printf.o -c
ar -rc libprintf.a printf.o
clean:
rm -rf *.o *.a
備注:-o參數用于指定輸出(out)文件名。不用-o的話,一般會在當前文件夾下生成默認的a.out文件作為可執行程序。
-c參數表示只編譯(compile)源文件但不鏈接,會把.c或.cc的c源程序編譯成目標文件。咱們這里是生成庫文件,所以也不需要鏈接。
使用ar工具進行打包成.a歸檔文件, -r將文件插入備存文件中, -c建立備存文件。
這里注意 庫名不能隨便亂起,一般是lib+庫名稱,后綴名是.a表示是一個歸檔文件,制作出來了靜態庫之后,發布時需要發布.a文件和.h文件。
至此靜態鏈接庫就制作完成。那如何引用它呢?
1.我們將上面制作好的libprintf.a文件和printf.h復制到一個新的test文件夾中。再新建一個test.c文件和一個makefile文件。
注意:test.c中頭文件應包含printf.h------>#include "printf.h" //(注意雙引號)
然后寫好main函數,在main函數中調用printf.c中寫好的測試函數。
2.接下來就是寫makefile
`
all:
gcc test.c -lprintf -L.
#注意-L后面的.
clean:
rm -rf *.o *.out
`
-l參數就是用來指定程序要鏈接的庫,-l參數緊接著就是庫名,那么庫名跟真正的庫文件名有什么關系呢?就拿數學庫來說,他的庫名是m,他的庫文件名是libm.so,很容易看出,把庫文件名的頭lib和尾.so去掉就是庫名了。
-L .,表示將當前目錄作為第一個尋找庫文件的目錄, 尋找的順序是:./–>/lib–>/usr/lib–>/usr/local/lib
注意:編譯時,必須得告訴編譯器靜態鏈接庫的名字和路徑(沒告訴的話會去默認路徑下查找),這點也很容易理解。
3.編譯后 執行a.out文件,即輸出printf.c中測試函數的內容,整個下來就是靜態鏈接庫的制作和使用。
三.linux下的動態鏈接庫
1.同樣新建一個printf.c printf.h 和makefile
2.makefile中編寫如下:gcc printf.c -o printf.o -c -fPIC<br/>gcc -o libprintf.so printf.o -shared <br/>
-fPIC參數是位置無關碼,-shared參數是按照共享庫的方式來鏈接。
此時生成的libprintf.so文件即動態鏈接庫文件,那么在發布的時候,發布libprintf.so和printf.h文件即可
3.同樣新建一個test文件,將libprintf.so與printf.h文件復制進去,新建一個test.c與makefile文件。
4.makefile寫法與靜態鏈接庫一致
`
all:
gcc test.c -lprintf -L.
#注意-L后面的.
clean:
rm -rf *.o *.out
`
但是由于靜態鏈接與動態鏈接實現的機制不同,具體哪些不同,請自行百度搜索,很多。
這里直接去執行./a.out是執行不成功的
報錯誤:
error while loading shared libraries: libprintf.so: cannot open shared object file: No such file or directory
原因是使用動態鏈接庫時,需要臨時加載動態鏈接庫,而不是在編譯時將庫里面的內容加載出來,編譯到一起。這是與靜態鏈接庫不同的地方。所以,它這里找不到庫文件在哪里,那么有一下幾種解決辦法:
(1)將libprintf.so放到固定目錄下就可以了,這個固定目錄一般是/usr/lib目錄。 cp libprintf.so /usr/lib即可
(2)使用環境變量LD_LIBRARY_PATH。操作系統在加載固定目錄/usr/lib之前,會先去LD_LIBRARY_PATH這個環境變量所指定的目錄下去尋找,如果找到就不用去/usr/lib下面找了,如果沒找到再去/usr/lib下面找。所以解決方案就是將libprintf.so所在的目錄導出到環境變量LD_LIBRARY_PATH中即可。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH: + 文件所在的路徑。
5.再去執行a.out即可執行成功。
四.總結
1.咱們注意到靜態鏈接庫與動態鏈接庫中 test文件夾中makefile,都有一句gcc test.c -lprintf -L,注意這個-lprintf參數,假如在文件夾中,又有靜態鏈接庫,又有動態鏈接庫,那編譯器該如何選擇呢? 答案是會優先選擇動態鏈接庫文件。
2.還有個nm命令也很有用,它可以用來查看一個.a或者.so文件中都有哪些符號,簡單來說就是看有哪些函數。
3.ldd命令(動態鏈接庫):作用是可以在一個使用了共享庫的程序執行之前解析出這個程序使用了哪些共享庫,并且查看這些共享庫是否能被找到,能被解析(決定這個程序是否能正確執行)。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。