Windows靜態庫和動態庫的建立和使用

來源:互聯網
上載者:User

 

偶們在實際的編程開發中,經常會遇到運行時無法找到某個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。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.