函數庫是通過頭文件聲明的函數原型,調用生成的鏈接庫文件(.a.so.dll)。
無需提供源碼。
動態鏈接庫與靜態鏈接庫
動態鏈接庫程序小,每次需要調用時訪問庫文件。依賴庫運行。
靜態鏈接庫程序大,是將相關庫文件函數直接嵌入代碼中。編譯完成后不依賴庫。
編譯調用庫函數的C代碼時,需要鏈接庫
比如使用math.h中函數的代碼編譯時
gcc abc.c -o app -lm//鏈接時可以用-lxxx來指示鏈接器去到libxxx.so中去查找這個函數。
1、自己制作靜態鏈接庫並使用
(1)第一步:自己制作靜態鏈接庫
首先使用gcc -c只編譯不連接,生成.o文件;然后使用ar工具進行打包成.a歸檔文件
庫名不能隨便亂起,一般是lib+庫名稱,后綴名是.a表示是一個歸檔文件
注意:制作出來了靜態庫之后,發布時需要發布.a文件和.h文件。
(2)第二步:使用靜態鏈接庫
把.a和.h都放在我引用的文件夾下,然后在.c文件中包含庫的.h,然后直接使用庫函數。
第一次,編譯方法:gcc Song.c -o app
報錯信息:test.c:(.text+0xa): undefined reference to `Song'
第二次,編譯方法:gcc test.c -o test -laston
報錯信息:/usr/bin/ld: cannot find -laston
collect2: error: ld returned 1 exit status
第三次,編譯方法:gcc Song.c -o app -laston -L.
無報錯,生成test,執行正確。
(3)除了ar名另外,還有個nm命令也很有用,它可以用來查看一個.a文件中都有哪些符號
Makefile
all: gcc Song.c -o Song.o -c ar -rc libSong.a Song.o
Song.c
#include<stdio.h> #include"Song.h" void Song() { printf("宋鵬飛\n"); } int Songpengfei(int a) { int i=0; for(i=0;i<a;i++) { printf("*"); } printf("\n"); }
Song.h
void Song(); int Songpengfei(int a);
2、自己制作動態鏈接庫並使用
代碼同上
Makefile
all: gcc Song.c -o Song.o -c -fPIC gcc -o libSong.so Song.o -shared
(1)動態鏈接庫的后綴名是.so(對應windows系統中的dll),靜態庫的擴展名是.a
(2)第一步:創建一個動態鏈接庫。
gcc Song.c -o Song.o -c -fPIC
gcc -o libSong.so Song.o -shared
-fPIC是位置無關碼,-shared是按照共享庫的方式來鏈接。
注意:做庫的人給用庫的人發布庫時,發布libxxx.so和xxx.h即可。
(3)第二步:使用自己創建的共享庫。
第一步,編譯方法:gcc Song.c -o app
報錯信息:test.c:(.text+0xa): undefined reference to `Song'
collect2: error: ld returned 1 exit status
第二步,編譯方法:gcc Song.c -o app -lSong
報錯信息:/usr/bin/ld: cannot find -lSong
collect2: error: ld returned 1 exit status
第三步,編譯方法:gcc Song.c -o app -lSong -L.
編譯成功
但是運行出錯,報錯信息:
error while loading shared libraries: libSong.so: cannot open shared object file: No such file or directory
錯誤原因:動態鏈接庫運行時需要被加載(運行時環境在執行test程序的時候發現他動態鏈接了libSong.so,於是乎會去固定目錄嘗試加載libSong.so,如果加載失敗則會打印以上錯誤信息。)
解決方法一:
將libSong.so放到固定目錄下就可以了,這個固定目錄一般是/usr/lib目錄。
cp libSong.so /usr/lib即可
解決方法二:使用環境變量LD_LIBRARY_PATH。操作系統在加載固定目錄/usr/lib之前,會先去LD_LIBRARY_PATH這個環境變量所指定的目錄下去尋找,如果找到就不用去/usr/lib下面找了,如果沒找到再去/usr/lib下面找。所以解決方案就是將libSong.so所在的目錄導出到環境變量LD_LIBRARY_PATH中即可。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/mnt/hgfs/linuxGX/c/D動態鏈接庫/cs
在ubuntu中還有個解決方案三,用ldconfig
(4)ldd命令:作用是可以在一個使用了共享庫的程序執行之前解析出這個程序使用了哪些共享庫,並且查看這些共享庫是否能被找到,能被解析(決定這個程序是否能正確執行)。