1. 程式人生 > >linux下的.a和.so,對比windows下的lib和dll

linux下的.a和.so,對比windows下的lib和dll

兩種庫

  • 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.顯示呼叫
需要了解以下幾個函式:

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)與符號(實際上就是欲呼叫的函式名),返回符號對應的函式的執行程式碼地址。由此地址,可以帶引數執行相應的函式。  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,他們分別指定標頭檔案的目錄和所連結的動態連結庫
# 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)
平常做專案可能不怎麼用到這些,不過一定要掌握vs或者qt等IDE裡面關於靜態庫和動態庫的匯入設定。