兩種庫
- Linux下的靜態庫以.a結尾(Winodws下為.lib)
- Linux下的動態庫以.so 或 .so.y結尾,其中y代表版本號(Windows下為.dll),而且,Linux下的庫必須以lib開頭,用於系統識別(如:libjpeg.a libsdl.so)
靜態庫必要的目標代碼的是在對程序編譯的時候被加入到程序中,而運行時不再需要.a的庫了
而動態庫,則是在運行時轉載
所以,動態鏈接的可執行代碼比靜態鏈接的可執行代碼小的多
把一個源代碼編譯成.so:
gcc -shared -o libtry.so try.c
而要生成靜態庫:
gcc -c try1.c gcc -c try2.c ar cqs libtry.a try1.o try2.o(或 ar r libtry.a try1.o try2.o)
庫的使用
靜態庫的使用
# gcc -c main.c -o main.o # gcc main.o -o name -L. -ltry (-l后面的名字就是我們上面生成的try庫)
動態庫的使用
動態庫分為顯式調用和隱式調用
1.顯示調用
需要了解以下幾個函數:
動態庫分為顯式調用和隱式調用
1.顯示調用
需要了解以下幾個函數:
const char *dlerror(void);
當動態鏈接庫操作函數執行失敗時,dlerror可以返回出錯信息,為NULL時表示操作函數執行成功。
void *dlopen(const char *filename, int flag);
成功則返回為void*的句柄。flag可以為RTLD_LAZY(表明在動態鏈接庫的函數代碼執行時解決);RTLD_NOW(表明在dlopen返回前就解決所有未定義的符號,一旦未解決,dlopen將返回錯誤)。filename為動態庫路徑。
void *dlsym(void *handle, char *symbol);
dlsym根據動態鏈接庫操作句柄(handle)與符號(實際上就是欲調用的函數名),返回符號對應的函數的執行代碼地址。由此地址,可以帶參數執行相應的函數。
dlsym根據動態鏈接庫操作句柄(handle)與符號(實際上就是欲調用的函數名),返回符號對應的函數的執行代碼地址。由此地址,可以帶參數執行相應的函數。
int dlclose (void *handle); 參數為動態鏈接庫的句柄。 顯式調用動態鏈接庫必須包含動態鏈接庫功能接口dlfcn.h(包含dl系列函數的聲明)和被調函數的聲明。
看起來還比較簡單,但是當你對動態鏈接庫函數使用比較頻繁的時候,就知道他的麻煩了,所以,不推崇。
2.隱式調用
所謂隱式調用,就是調用的時候直接使用動態庫中的函數,並不區別對待。
但是在隱式調用的時候必須要讓程序能找到你所調用的函數的所屬動態庫。
我們先來建立一個感性認識:
所謂隱式調用,就是調用的時候直接使用動態庫中的函數,並不區別對待。
但是在隱式調用的時候必須要讓程序能找到你所調用的函數的所屬動態庫。
我們先來建立一個感性認識:
# more /etc/ld.so.conf 你會看到以下內容: /usr/kerberos/lib /usr/X11R6/lib /usr/lib/sane /usr/lib/qt-3.1/lib /usr/lib/mysql /usr/lib/qt2/lib /usr/local/lib /usr/local/BerkeleyDB.4.3/lib
ld.so.conf是系統對動態鏈接庫進行查找的路徑配置文件,也就是說該文件是系統鏈接工具/usr/bin/ld查找動態鏈接庫的地圖,所以,要達到我們的目的有以下幾種方法:
a.將自己的動態鏈接庫文件拷到以上路徑的目錄下
# cp libwx.so.1 /usr/local/lib
b.將自己動態鏈接庫文件的路徑加入到該文件中
# vi /etc/ld.so.conf, 然后加入自己的路徑(或pwd >>/etc/ld.so.conf)
(千萬不要將>>寫成>,前者是添加,后者是覆蓋)
c.把當前路徑加入環境變量LD_LIBRARY_PATH,其實就是/usr/bin/ld的環境變量
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
編譯的時候:
# gcc -o try main.c libtry.so.1
如果沒有讓/usr/bin/ld知道你的動態鏈接庫在哪,編譯的時候就要告訴它:
# gcc -o try main.c /root/libtry.so.1 ( 或:# gcc -L/root/wx -o qqq main.c libmy.so.1)
-L指定動態鏈接庫所在的目錄,有時候用gcc還會碰到-I,-l,他們分別指定頭文件的目錄和所鏈接的動態鏈接庫
# cp libwx.so.1 /usr/local/lib
b.將自己動態鏈接庫文件的路徑加入到該文件中
# vi /etc/ld.so.conf, 然后加入自己的路徑(或pwd >>/etc/ld.so.conf)
(千萬不要將>>寫成>,前者是添加,后者是覆蓋)
c.把當前路徑加入環境變量LD_LIBRARY_PATH,其實就是/usr/bin/ld的環境變量
# export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
編譯的時候:
# gcc -o try main.c libtry.so.1
如果沒有讓/usr/bin/ld知道你的動態鏈接庫在哪,編譯的時候就要告訴它:
# gcc -o try main.c /root/libtry.so.1 ( 或:# gcc -L/root/wx -o qqq main.c libmy.so.1)
-L指定動態鏈接庫所在的目錄,有時候用gcc還會碰到-I,-l,他們分別指定頭文件的目錄和所鏈接的動態鏈接庫
# ldd try 用來查看可執行文件qqq的動態鏈接庫的依賴關系
如
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x00867000)
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0x0638a000)
libc.so.6 => /lib/tls/libc.so.6 (0x0046d000)
libm.so.6 => /lib/tls/libm.so.6 (0x00598000)
libdl.so.2 => /lib/libdl.so.2 (0x005bd000)
libasound.so.2 => /lib/libasound.so.2 (0x062e1000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x005d5000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x0069e000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x006ae000)
/lib/ld-linux.so.2 (0x00450000)
如
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x00867000)
libSDL-1.2.so.0 => /usr/lib/libSDL-1.2.so.0 (0x0638a000)
libc.so.6 => /lib/tls/libc.so.6 (0x0046d000)
libm.so.6 => /lib/tls/libm.so.6 (0x00598000)
libdl.so.2 => /lib/libdl.so.2 (0x005bd000)
libasound.so.2 => /lib/libasound.so.2 (0x062e1000)
libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x005d5000)
libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x0069e000)
libpthread.so.0 => /lib/tls/libpthread.so.0 (0x006ae000)
/lib/ld-linux.so.2 (0x00450000)
平常做項目可能不怎么用到這些,不過一定要掌握vs或者qt等IDE里面關於靜態庫和動態庫的導入設置。
本文結束。