天天看點

導入庫和靜态庫

目前以lib字尾的庫有兩種,一種為靜态連結庫(Static Library,以下簡稱“靜态庫”),另一種為動态連接配接庫(DLL,以下簡稱“動态庫”)的導入庫(Import Library,以下簡稱“導入庫”)。

靜态庫是一個或者多個obj檔案的打包,是以有人幹脆把從obj檔案生成lib的過程稱為Archive,即合并到一起。比如你連結一個靜态庫,如果其中有錯,它會準确的找到是哪個obj有錯,即靜态lib隻是殼子。

動态庫一般會有對應的導入庫,友善程式靜态載入動态連結庫,否則你可能就需要自己LoadLibrary調入DLL檔案,然後再手工GetProcAddress獲得對應函數了。有了導入庫,你隻需要連結導入庫後按照頭檔案函數接口的聲明調用函數就可以了。

導入庫和靜态庫的差別

導入庫和靜态庫的差別很大,他們實質是不一樣的東西。靜态庫本身就包含了實際執行代碼、符号表等等,而對于導入庫而言,其實際的執行代碼位于動态庫中,導入庫隻包含了位址符号表等,確定程式找到對應函數的一些基本位址資訊。

這也是實際上很多開源代碼釋出的慣用方式:

1. 預編譯的開發包:包含一些.dll檔案和一些.lib檔案。其中這裡的.lib就是導入庫,而不要錯以為是靜态庫。但是引入方式和靜态庫一樣,要在連結路徑上添加找到這些.lib的路徑。而.dll則最好放到最後産生的應用程式exe執行檔案相同的目錄。這樣運作時,就會自動調入動态連結庫。

2. 使用者自己編譯: 下載下傳的是源代碼,按照readme自己編譯。生成很可能也是.dll + .lib(導入庫)的庫檔案

3. 如果你隻有dll,并且你知道dll中函數的函數原型,那麼你可以直接在自己程式中使用LoadLibary調入DLL檔案,然後使用GetProcAddress調用DLL中的函數。

當DLL被連結時,連結程式要查找關于輸出變量,函數,或C++類的資訊,并自動生成一個lib檔案。該lib檔案包含一個DLL輸出的符号清單。如果要連結引用該DLL的輸出符号的任何可執行子產品,該lib檔案是必不可少的(使用GetProcAddress除外)。

其實導入庫中并不含RVA(每個符号的相對虛拟位址),隻是一些符号而已,還有關于這個lib所對應的DLL的名字等。 (這隻是我現在的了解)

那當應用程式調用一個DLL的函數時,是怎麼進行的呢?(使用lib的情況下)

答案是在程序的主線程開始運作之前,由加載器完成。

加載器根據輸入節中DLL的名字按照windows的搜尋路徑搜尋DLL,找到後DLL映射到程序的位址空間,這是DLL中對應于輸入節中的各個符号的位址就可以确定了,加載器在這個時候将位址重新填入可執行子產品的輸入節中,動态連接配接完成。

繼續閱讀