天天看點

[轉]LIB和DLL的差別與使用

原文位址:

http://www.cppblog.com/amazon/archive/2011/01/01/95318.html

共有兩種庫:

一種是LIB包含了函數所在的DLL檔案和檔案中函數位置的資訊(入口),代碼由運作時加載在程序空間中的DLL提供,稱為動态連結庫dynamic link library。

一種是LIB包含函數代碼本身,在編譯時直接将代碼加入程式當中,稱為靜态連結庫static link library。

共有兩種連結方式:

動态連結使用動态連結庫,允許可執行子產品(.dll檔案或.exe檔案)僅包含在運作時定位DLL函數的可執行代碼所需的資訊。

靜态連結使用靜态連結庫,連結器從靜态連結庫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/Library Module中加入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檔案(或者在源代碼中加入指令#pragma comment(lib, “Lib.lib”)),并将.dll檔案置入工程所在目錄,然後添加對應的.h頭檔案。

[轉]LIB和DLL的差別與使用

#include "stdafx.h"

[轉]LIB和DLL的差別與使用

#include "DLLSample.h"

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

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

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

int main()

[轉]LIB和DLL的差別與使用

{

[轉]LIB和DLL的差別與使用

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

[轉]LIB和DLL的差別與使用

        return(1);

[轉]LIB和DLL的差別與使用

}

[轉]LIB和DLL的差別與使用

(2)顯式連結

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

[轉]LIB和DLL的差別與使用

#include <iostream>

[轉]LIB和DLL的差別與使用

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

[轉]LIB和DLL的差別與使用

typedef void (*DLLFunc)(int);

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

        DLLFunc dllFunc;

[轉]LIB和DLL的差別與使用

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

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

        if (hInstLibrary == NULL)

[轉]LIB和DLL的差別與使用

        {

[轉]LIB和DLL的差別與使用

          FreeLibrary(hInstLibrary);

[轉]LIB和DLL的差別與使用

        }

[轉]LIB和DLL的差別與使用

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

[轉]LIB和DLL的差別與使用

        if (dllFunc == NULL)

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

        dllFunc(123);

[轉]LIB和DLL的差別與使用

        std::cin.get();

[轉]LIB和DLL的差別與使用

        FreeLibrary(hInstLibrary);

[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用
[轉]LIB和DLL的差別與使用

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環境變量中的一系列目錄

本文轉自火地晉部落格園部落格,原文連結:http://www.cnblogs.com/yelaiju/archive/2012/11/26/2789306.html,如需轉載請自行聯系原作者