static lib和dynamic lib


lib分為 staticlib 和 dynamic lib:

靜態lib將導出聲明和實現都放在lib中,編譯后所有代碼都嵌入到宿主程序, 鏈接器從靜態鏈接庫LIB獲取所有被引用函數,並將庫同代碼一起放到可執行文件中。

動態lib相當於一個h文件,是對實現部分(.dll文件)的導出部分的聲明,編譯后只是將導出聲明部分編譯到宿主程序中,運行時候需要相應的dll文件支持, 包含了函數所在的DLL文件和文件中函數位置的信息(入口),代碼由運行時加載在進程空間中的DLL提供,稱為動態鏈接庫dynamic link library。

lib文件是不對外公開的,不能查看一個編譯過后的文件。

關於lib和dll的區別如下:

(1)lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。

(2)如果有dll文件,那么lib一般是一些索引信息,記錄了dll中函數的入口和位置,dll中是函數的具體內容;如果只有lib文件,那么這個lib文件是靜態編譯出來的,索引和實現都在其中。使用靜態編譯的lib文件,在運行程序時不需要再掛動態庫,缺點是導致應用程序比較大,而且失去了動態庫的靈活性,發布新版本時要發布新的應用程序才行。

(3)動態鏈接的情況下,有兩個文件:一個是LIB文件,一個是DLL文件。LIB包含被DLL導出的函數名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件鏈接到DLL文件。在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中相應函數代碼的地址,從而節省了內存資源。DLL和LIB文件必須隨應用程序一起發行,否則應用程序會產生錯誤。如果不想用lib文件或者沒有lib文件,可以用WIN32 API函數LoadLibrary、GetProcAddress裝載。

使用lib需注意兩個文件:

(1).h頭文件,包含lib中說明輸出的類或符號原型或數據結構。應用程序調用lib時,需要將該文件包含入應用程序的源文件中。

(2).LIB文件。

使用dll需注意三個文件:

(1).h頭文件,包含dll中說明輸出的類或符號原型或數據結構的.h文件。應用程序調用dll時,需要將該文件包含入應用程序的源文件中。

(2).LIB文件,是dll在編譯、鏈接成功之后生成的文件,作用是當其他應用程序調用dll時,需要將該文件引入應用程序,否則產生錯誤。如果不想用lib文件或者沒有lib文件,可以用WIN32 API函數LoadLibrary、GetProcAddress裝載。

(3).dll文件,真正的可執行文件,開發成功后的應用程序在發布時,只需要有.exe文件和.dll文件,並不需要.lib文件和.h頭文件。

 

使用lib的方法:

靜態lib中,一個lib文件實際上是任意個obj文件的集合,obj文件是cpp文件編譯生成的。在編譯這種靜態庫工程時,根本不會遇到鏈接錯誤;即使有錯,也只會在使用這個lib的EXT文件或者DLL工程里暴露出來。

在VC中新建一個static library類型的工程Lib,加入test.cpp文件和test.h文件(頭文件內包括函數聲明),然后編譯,就生成了Lib.lib文件。

別的工程要使用這個lib有兩種方式:

(1)在project->link->Object/LibraryModule中加入Lib.lib文件(先查詢工程目錄,再查詢系統Lib目錄);或者在源代碼中加入指令#pragma comment(lib, “Lib.lib”)。

(2)將Lib.lib拷入工程所在目錄,或者執行文件生成的目錄,或者系統Lib目錄中。

(3)加入相應的頭文件test.h。

使用DLL的方法:

使用動態鏈接中的lib,不是obj文件的集合,即里面不會有實際的實現,它只是提供動態鏈接到DLL所需要的信息,這種lib可以在編譯一個DLL工程時由編譯器生成。

創建DLL工程的方法(略)。

(1)隱式鏈接

第一種方法是:通過project->link->Object/Library Module中加入.lib文件(或者在源代碼中加入指令#pragmacomment(lib, “Lib.lib”)),並將.dll文件置入工程所在目錄,然后添加對應的.h頭文件。

 #include "stdafx.h"

 #include "DLLSample.h"

 #pragma comment(lib,"DLLSample.lib") //你也可以在項目屬性中設置庫的鏈接

 int main()

 {

       TestDLL(123);//dll中的函數,在DllSample.h中聲明

 return(1);

 }

 

(2)顯式鏈接

需要函數指針和WIN32 API函數LoadLibrary、GetProcAddress裝載,使用這種載入方法,不需要.lib文件和.h頭文件,只需要.dll文件即可(將.dll文件置入工程目錄中)。

 #include <iostream>

 #include <windows.h> //使用函數和某些特殊變量

 typedef void (*DLLFunc)(int);

 int main()

 {

 DLLFunc dllFunc;

 HINSTANCE hInstLibrary =LoadLibrary("DLLSample.dll");

 

 if (hInstLibrary == NULL)

 {

 FreeLibrary(hInstLibrary);

 }

 dllFunc =(DLLFunc)GetProcAddress(hInstLibrary, "TestDLL");

 if (dllFunc == NULL)

 {

 FreeLibrary(hInstLibrary);

 }

 dllFunc(123);

 std::cin.get();

 FreeLibrary(hInstLibrary);

 return(1);

 }

 

LoadLibrary函數利用一個名稱作為參數,獲得DLL的實例(HINSTANCE類型是實例的句柄),通常調用該函數后需要查看一下函數返回是否成功,如果不成功則返回NULL(句柄無效),此時調用函數FreeLibrary釋放DLL獲得的內存。

GetProcAddress函數利用DLL的句柄和函數的名稱作為參數,返回相應的函數指針,同時必須使用強轉;判斷函數指針是否為NULL,如果是則調用函數FreeLibrary釋放DLL獲得的內存。此后,可以使用函數指針來調用實際的函數。

最后要記得使用FreeLibrary函數釋放內存。

注意:應用程序如何找到DLL文件?

使用LoadLibrary顯式鏈接,那么在函數的參數中可以指定DLL文件的完整路徑;如果不指定路徑,或者進行隱式鏈接,Windows將遵循下面的搜索順序來定位DLL:

(1)包含EXE文件的目錄

(2)工程目錄

(3)Windows系統目錄

(4)Windows目錄

(5)列在Path環境變量中的一系列目錄

補充:

dll是個編譯好的程序,調用時可以直接調用其中的函數, 不參加工程的編譯. 而lib應該說是一個程序集, 只是把一些相應的函數總結在一起,如果調用lib中的函數, 在工程編譯時,這些調用的函數都將參加編譯. 簡單講,靜態庫就是直接將需要的代碼連接進可執行程序;動態庫就是在需要調用其中的函數時,根據函數映射表找到該函數然后調入堆棧執行。做成靜態庫可執行文件本身比較大,但不必附帶動態庫 做成動態庫可執行文件本身比較小,但需要附帶動態庫 其它沒有什么對於程序員而言很大的區別 有的Unix可能不支持動態庫,所以只好用靜態庫 DLL與LIB的區別: 1.DLL是一個完整程序,其已經經過鏈接,即不存在同名引用,且有導出表,與導入表 lib是一個代碼集(也叫函數集)他沒有鏈接,所以lib有冗余,當兩個lib相鏈接時地址會重新建立,當然還有其它相關的不同,用lib.exe就知道了 2.在生成dll時,經常會生成一個.lib(導入與導出),這個lib實際上不是真正的函數集,其每一個導出導入函數都是跳轉指令,直接跳轉到DLL中的位置,這個目的是外面的程序調用dll時自動跳轉 3.實際上最常用的lib是由lib.exe把*.obj生成的lib,這才是真正的

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM