導入庫
出自 MBA智库百科(https://wiki.mbalib.com/)
目錄 |
導入庫只包含了地址符號表等,確保程式找到對應函數的一些基本地址信息。
目前以lib尾碼的庫有兩種,一種為靜態鏈接庫(Static Library,以下簡稱“靜態庫”),另一種為動態連接庫(DLL,以下簡稱“動態庫”)的導入庫(ImportLibrary,以下簡稱“導入庫”)。
靜態庫是一個或者多個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中對應於輸入節中的各個符號的地址就可以確定了,載入器在這個時候將地址重新填入可執行模塊的輸入節中,動態連接完成。