靜態(隱式)調用/動態(顯式)調用-動態鏈接庫和靜態鏈接庫

靜態調用-動態鏈接庫

靜態調用動態鏈接庫是隱式調用。隱式鏈接調用就是在程序開始執行時就將dll文件加載到程序當中且整個執行過程無法分離。調用十分簡單,但需要h,lib和dll文件的支持。
程序員在建立一個DLL文件時,鏈接程序會自動生成一個與之對應的LIB導入文件,該文件包含了每一個DLL導出函數的符號名和可選的標識號,但是並不含有實際的代碼。LIB文件作爲DLL的替代文件被編譯到應用程序項目中。當程序員通過靜態鏈接方式編譯生成應用程序時,應用程序中的調用函數與LIB文件中導出符號相匹配,這些符號或標識號進入到生成的EXE文件中。 LIB文件中也包含了對應的DLL文件名(但不是完全的路徑名),鏈接程序將其存儲在EXE文件內部。當應用程序運行過程中需要加載DLL文件時,Windows根據這些信息發現並加載DLL,然後通過符號名或標識號實現對DLL函數的動態鏈接。

動態調用-動態鏈接庫

顯式鏈接調用是執行過程中隨時可以加載或卸載dll文件。調用較麻煩但可以脫離h和lib,只需要dll文件。顯式鏈接具有更好的靈活性,在工程較大時可以節省內存。對於解釋性語言更爲合適,也節省了編譯時間。顯示調用可以利用指針實現多態。

靜態鏈接庫

靜態庫與動態庫區別
靜態鏈接庫的後綴名爲lib,動態鏈接庫的導入庫的後綴名也爲lib。不同的是,靜態庫中包含了函數的實際執行代碼,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息;
由於靜態庫是在編譯期間直接將代碼合到可執行程序中,而動態庫是在執行期時調用DLL中的函數體,所以執行速度比動態庫要快一點;
靜態庫鏈接生成的可執行文件體積較大,且包含相同的公共代碼,造成內存浪費;
使用動態鏈接庫的應用程序不是自完備的,它依賴的DLL模塊也要存在,如果使用載入時動態鏈接,程序啓動時發現DLL不存在,系統將終止程序並給出錯誤信息。而使用運行時動態鏈接,系 統不會終止,但由於DLL中的導出函數不可用,程序會加載失敗;
DLL文件與EXE文件獨立,只要輸出接口不變(即名稱、參數、返回值類型和調用約定不變),更換DLL文件不會對EXE文件造成任何影響,因而極大地提高了可維護性和可擴展性,適用於大規模的軟件開發,使開發過程獨立、耦合度小,便於不同開發者和開發組織之間進行開發和測試。

  • Windows

    • 靜態庫:函數和數據被編譯進一個二進制文件(.lib)(一個或多個obj文件打包),在編譯鏈接可執行文件時,鏈接器從庫中複製這些函數和數據並把它們和應用程序的其他模塊組合起來創建最終的可執行文件(.exe)。

    • 動態庫:使用動態庫時,往往提供兩個文件:引入庫(後綴也爲.lib)、動態鏈接庫(.DLL)。引入庫包含被DLL導出的函數和變量的符號名,DLL包含實際的函數和數據。在編譯鏈接可執行文件時,只需要鏈接引入庫,DLL中的函數代碼和數據並不可複製到可執行文件中,在運行時,再去加載DLL,訪問DLL中導出的函數。

    • 隱式調用:在編譯/鏈接階段完成,由編譯系統根據動態庫的頭文件和庫文件進行編譯和鏈接,即需要將引入庫加入到應用程序的工程中,從而確定待調用的的函數原型和地址。

    • 顯示調用:利用API函數實現加載和卸載DLL,獲取調用函數地址獲取錯誤信息等功能。

  • Linux

    • 靜態庫:與Windows下的靜態庫類似,後綴名爲.a。

    • 動態庫:與Windows下動態庫類似,沒有引入庫,後綴名爲.so。

    • 隱式調用:編譯可執行程序時需要指定庫文件的搜索路徑。

    • 顯式調用:顯式調用編譯可執行程序時不用加上動態庫的搜索路徑(因爲已經在主函數中包含了庫文件的路徑),但是需要增加幾個系統調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章