.dll,.lib,.def 和 .exp檔案

來源:互聯網
上載者:User
 簡要的介紹一下在微軟開發工具中(VC)靜態連結庫和動態連結程式庫產生過程中出現的.dll  .lib  .def 和 .exp檔案類型。windows平台上可執行檔可能是一個.exe檔案也可能四個.dll檔案。當然也有一些比較特別的exe或者dll檔案,不過他們有其他樣式的尾碼名比如屏保程式(.scr),ActiveX DLL 用的.ocx 還有各種驅動使用的各種副檔名。這裡我們不討論.com 和一些指令檔比如.bat .cmd等,雖然他們仍然是可執行檔。

    庫就是包含著一坨資料和代碼的東西,這個東西可以被串連程式或者其他可執行檔使用。庫中這些可使用的對象(資料或者函數)使用一些標記標出來。比如在.obj目標檔案中一些簡單的符號。這裡討論到兩種類型的連結庫,靜態連結庫和動態連結程式庫。

     你可以認為靜態連結庫是一堆目標檔案(.obj)檔案的集合,我們只是把他們簡單的打包在了一半靜態連結庫中。靜態連結庫都有一個.lib的副檔名。靜態連結庫不是用來執行的但它可以被連結程式(link.exe)在產生可執行檔的時候使用。在預設的情況下,靜態連結庫中所有的符號標記對於linker來說都是可見的,即可使用的。當然在編譯你的時候你需要對應好標頭檔和靜態連結庫,一個靜態連結庫和.def 或者.exp檔案沒有任何的關係。

    這裡一個缺點就是,當我們使用靜態連結庫連結產生程式的時候,它裡面的一些對象比如函數代碼都會拷貝到對應的程式當中去,這個工作原理和.obj檔案的使用時的工作原理是一樣的。對於一些在不同應用程式中可重複利用的代碼來說這並不是意見好事:當我們連結的時候,每一個應用程式中都會有一個.obj中使用到的對象的拷貝。

    動態連結程式庫(DLL,在Unix世界中被稱作共用目標即.so檔案)可以幫我們節省記憶體空間。當我們連結到一個dll的時候,不會有代碼拷貝到目標可執行檔裡面,但是會有一個引用放在可執行檔裡面。當可執行檔被載入執行的時候系統會檢查它使用到的dll然後載入這些dll。使用dll我們可以很方便的升級我們的用戶端程式,而不用再次更新可執行檔。

    但是在連結linking的時候我們還必須有一些資訊來知道怎樣連結到dll,比如標頭檔中對應dll中的一些函數的簽名。連結程式需要更多的資訊,比如dll的檔案名稱,那些符號可用等等,這些資訊存在於匯出庫檔案中。匯出庫的尾碼名也是一個.lib。當linker產生.dll檔案的時候,他會自動的產生一個匯出庫.lib檔案。匯出庫被用來分發給那些在開發階段使用到這個dll的研發人員,更精確的說,是在他們使用link的時候。在使用的時候匯出庫的使用和靜態連結庫的使用基本沒啥區別。就是使用匯出庫的程式在執行的時

候需要對應匯出庫的dll。

     好吧!問題看似解決了,但是為什麼我們會看到到處都會出現一些.def檔案啊?

     def檔案(module definition file模組定義檔案)是用來建立dll和對應的匯出庫的。在一個.def檔案中,你可以指定dll將會匯出哪些符號給使用者使用。linker會根據def檔案的說明來產生dll和lib。一般的,dll的使用者不會對def檔案感興趣(我是指使用dll的開發人員和使用最終產品的使用者)。注意他和靜態連結庫的不同點,預設的情況下,dll內部的符號是不可見的。我們有方法讓他們可見--在def檔案中使用exports語句。但是我們還有其他的方法,比如zaidll的原始碼中使用__declspec(dllexport)或者在linker的選項中

使用 /EXPORT 選項來匯出一個函數等等。事實上現在__declspec(dllexport)使用很多,而def檔案很少使用了。使用def檔案,你可以指示連結程式linker其他的一些資訊而不是匯出動作,比如堆棧的大小等等。但是這些選項經常在linker的命令列中標明了。事實上,def檔案在早期win16的dll編程中使用現在在win32中我們基本上把它給拋棄了,以後也是如此。

     稍等,在某些地方我們還看到一些.exp檔案?exp檔案就是匯出檔案(export file)。在前面的討論中,我們討論了使用linker去建立dll(中間還有它的匯出庫)現在,我們假設我們產生兩個dll(or just executables)。但是他們都需要調用一些對方中函數,問題出現了。當我們產生a.dll的時候我們需要b.lib;但是b.lib在對應的b.dll產生之前沒有產生,而b.dll的產生又需要a.lib。正因如此,微軟的解決辦法是使用exp檔案,或者叫匯出檔案。在產生兩個dll之前,你使用lib.exe(library mangager tool庫管理工具)來建立一個.lib和.exp,即,DLL A 的a.lib 和a.exp,現在linker使用a.lib和DLL B 自己的東西去產生b.dll和b.lib。當你回來連結DLL A的時候你就有了b.lib。這裡linker需要知道a.dll中需要匯出處啥。這些資訊都被緩衝到了a.exp檔案中。linker不需要def檔案或者/EXPORT選項,它僅僅是載入a.exp中的資訊。a.exp就像a.dll的兩個產生過程(lib.exe and linker)的聯絡者一樣。相似的,linker不會再次產生a.lib。總的來說,這種迴圈調用的情況不會和在我們的程式中出現,因此,希望你不會再你的程式中用到exp檔案。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.