1. 程式人生 > >Windows靜態庫和動態庫的創建和使用(VS2005)

Windows靜態庫和動態庫的創建和使用(VS2005)

spec 占用內存 庫文件 工程 存在 中間 開發程序 文件的 系統

偶們在實際的編程開發中,經常會遇到運行時無法找到某個DLL文件或者鏈接時無法找到某個LIB文件。然後,我們就開始亂GOOGLE一下,然後將VS2005的設置改變一下,或許就Ok了,我們將別人開發的DLL或者LIB導入到我們的編程中,那麽這些lib,DLL到底是什麽呢?下面,偶就細細道來。

首先,偶們說第一個:靜態鏈接庫(Static Libary)

偶們用VS2005做一個靜態鏈接庫先

打開VS2005,新建à項目(staticCai)àWin32控制臺應用程序

新建static_lib.h 和static_lib.cpp 兩個文件,這兩個文件的內容如下:

static_lib.h:

int add(int x,int y);

int substract(int x , int y);

static_lib.cpp:

#include "static_lib.h"

int add(int x,int y)

{

return x + y;

}

int substract(int x,int y)

{

return x - y;

}

然後編譯,生成解決方案,好,這樣不出意外會在debug文件夾(與staticCai並列)下生成一個staticCai.lib文件,好了,這個就是我們做好的靜態鏈接庫。下面,我們看看怎麽用這個靜態鏈接庫。我們再新建一個win32控制臺程序,新建main.cpp內容如下:

#include <iostream>

#include "static_lib.h"

#pragma comment(lib, "static.lib")

using namespace std ;

int main()

{

cout << add(3 ,4) << endl ;

cout << substract(5 , 3) << endl ;

return 0 ;

}

並且將staticCai.lib和static_lib.h這兩個文件拷貝到與main.cpp並列的文件夾下。然後,我們編譯,鏈接,執行程序,就會出結果了

#pragma comment(lib, "static.lib")這句和我們在 項目à屬性à連接器à添加依賴項 的效果是一樣的。至此,怎麽做靜態鏈接庫以及怎麽用靜態鏈接庫就搞定了。現在,我們把剛剛拷貝過來的staticCai.lib給刪了,我們發現,程序照樣執行,但是不能再鏈接了。所以,我們得出這樣的結論:我們再鏈接的時候需要靜態鏈接庫,一旦鏈接成功,生成了可執行文件,那麽,靜態鏈接庫就不再需要了。

其次,偶們說第二個:動態鏈接庫(dynamic link Libary)

同樣,我們來做一個動態鏈接庫,和上面的步驟一樣,先建工程,只有最後一步稍有不同

然後,新建Dll.cpp文件(這裏我們就不做.h文件了),敲入一下內容:

#define DLL_API _declspec(dllexport)

#include <iostream>

using namespace std;

DLL_API int add(int a,int b) //實現兩個整數相加

{

return a+b;

}

DLL_API int subtract(int a,int b) //實現兩個整數相減

{

return a-b;

}

然後,我們編譯,生成解決方案,就會在debug文件夾下生成dllCai.dll和dllCai.lib。好,至此,動態鏈接庫就做好了,下面我們來看怎麽用,新建一個win32控制臺程序,新建main.cpp內容如下:

#include <iostream>

using namespace std ;

#pragma comment(lib, "DLL.lib")

extern int add(int a,int b);

extern int subtract(int a,int b);

int main()

{

cout << add(3 ,4) << endl ;

cout << subtract(5 , 3) << endl ;

return 0 ;

}

然後把dllCai.dll和dllCai.lib拷貝到與main.cpp並列的目錄下。接著,編譯,鏈接,執行,就會看到和上一次一樣的結果了。然後,我們把dllCai.lib給刪了,程序照樣執行,但是不能再鏈接了,接著,我們把dllCai.dll給刪了,程序可以再編譯,鏈接,但是執行的時候就黃了。所以,我們說:對於動態鏈接庫,鏈接的時候需要.lib文件,運行的時候需要.dll文件。

至此,靜態鏈接庫和動態鏈接庫我們就說完了,我們做一下對比和補充:

1 、 兩個lib文件

我們發現,無論是靜態鏈接庫還是動態鏈接庫,最後都有lib文件,那麽兩者區別是什麽呢?其實,兩個是完全不一樣的東西。staticCai.lib的大小為4KB,dllCai.lib的大小為2KB,靜態庫對應的lib文件叫靜態庫,動態庫對應的lib文件叫導入庫。實際上靜態庫本身就包含了實際執行代碼、符號表等等,而對於導入庫而言,其實際的執行代碼位於動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。

2 、 對於靜態鏈接庫,我們在編譯和鏈接的時候已經將所有的代碼都導入進來,因此,當生成可執行文件以後,可執行文件包含所有的代碼。因此,在可執行文件運行時就不再需要靜態庫了,這也是為什麽我們刪掉staticCai.lib程序照樣執行;而對於動態鏈接庫,實際上,可執行文件不包含DLL中的內容,只是通過導入庫(.lib)知道了相應的地址信息,因此,可執行文件在運行時動態得去加載DLL,這也是為什麽我們刪掉dllCai.dll後程序就不能執行了。

3 、 對於DLL,我們是可以不要lib文件的。

如果不要lib文件,我們可以通過函數指針的使用達到我們的目的:

#define DLL_API _declspec(dllexport)

#include <iostream>

using namespace std; //註意這裏的extern "C" , 這裏必須加

extern "C" DLL_API int add(int a,int b) //實現兩個整數相加

{

return a+b;

}

extern "C" DLL_API int subtract(int a,int b) //實現兩個整數相減

{

return a-b;

}

#include <iostream>

#include <Windows.h>

using namespace std ;

typedef int (*func)(int x , int y); //函數指針

int main()

{

HINSTANCE hInstance = LoadLibrary("DLL.dll");

if(hInstance == NULL)

{

cout << "SB" << endl ;

return 0;

}

func add = (func)GetProcAddress(hInstance, "add");

func sub = (func)GetProcAddress(hInstance, "subtract");

cout << (*add)(3,4) << endl ;

cout << (*sub)(5,3) << endl ;

}

顯然,這種方法沒有用lib文件方便,如果為了每次調用一個函數還要自己再弄一個函數指針,多麻煩啊,所以,我們在實際開發中,用的眾多的第三方擴展庫,別人都是提供的:

.h 文件(類,函數的聲明)

.dll 文件(類或函數的實現)

.lib 文件(導入庫)

小結:

一、靜態庫

* 靜態庫是把程序運行時需要使用的函數編譯在一個二進制文件中,擴展名為.lib。當程序link時把靜態庫中的二進制數據和程序其它數據放到一起。程序運 行時不在需要lib和dll文件的支持。這樣做的壞處是開發出來的程序占用磁盤空間較大。特別是windows系統中本來就有或很多程序運行都需要的函數 完全沒有必要每次開發程序時都要使用各自的靜態庫。

* 靜態庫為.lib文件形式存在

* 鏈接後產生的可執行文件包含了所有需要調用的函數的代碼,因此占用磁盤空間較大

* 如果有多個(調用相同庫函數的)進程在內存中間時運行,內存中就存有多份相同的庫函數代碼,因此占用內存空間較多。

二、動態庫

* 動態庫在開發時僅是把dll中的函數名和參數放到應用程序中,應用程序運行時根據函數名和參數調用dll中的函數來運行,這樣操作系統中的應用程序可以同 時使用同一個dll。可以有效地節省硬盤空間,當然這樣做使得程序設計更有層次。也有利於軟件工程師的分工和信息安全

* 動態庫以.dl文件形式存在,且一般都有一個對應的引入庫以.lib文件形式存在。純資源dll不生成.lib引入庫。

>引入庫和靜態庫的擴展名均為*.lib,但是引入庫僅包含一些函數名和參數信息,沒有函數體,是為調用動態庫服務的,它和動態庫的關系相當於.h文件和.cpp文件之間的關系;

* 動態庫兩種綁定方式

>靜態綁定(static blnding) 使用靜態綁定的程序在一開始載入內存的時候,載入程序就會把程序所有調用到的動態代碼的地址算出、確定下來。這種方式使程序剛運行時的初始化時間較長,不過一但完成動態裝載,程序的運行速度就很快。

2動態綁定(dynamic binding) 使用這種方式的程序並不在一開始就完成動態鏈接,而是直到真正調用動態庫代碼時,載入程序才計算(被調用的那部分)動態代碼的邏輯地址,然後等到某個時 候,程序又需要調用另外某塊動態代碼時,載入程序才又去計算這部分代碼的邏輯地址。所以,這種方式侄程序初始化時間較短,但運行期間的性能比不上靜態綁定 的程序。

* 使用動態庫的兩種方法(windows)

>方法一: load-time dynamic linking
在要調用dll的應用程序鏈接時,將dll的輸入庫文件(import library,.lib文件)包含進去。具體的做 法是在源文件開頭加一句#include ,然後就可以在源文件中調用dlldemo.dll中的輸出文件了。

>方法二: run-time dynamic linking

不必在鏈接時包含輸入庫文件,而是在源程序中使用LoadLibrary或LoadLibraryEx動態的載入dll。

http://blog.csdn.net/zuichudeheart/article/details/43093897?ref=myread

http://blog.csdn.net/cocoasprite/article/details/43167483

Windows靜態庫和動態庫的創建和使用(VS2005)