C++編寫一個簡單的DLL

  • 什麼是DLL:

自從微軟推出16位的Windows操做系統起,此後每種版本的Windows操做系統都很是依賴於動態連接庫(DLL)中的函數和數據,實際上 Windows操做系統中幾乎全部的內容都由DLL以一種或另一種形式表明着,例如顯示的字體和圖標存儲在GDI DLL中、顯示Windows桌面和處理用戶的輸入所須要的代碼被存儲在一個User DLL中、Windows編程所須要的大量的API函數也被包含在Kernel DLL中。
html

DLL是創建在客戶/服務器通訊的概念上,包含若干函數、類或資源的庫文件,函數和數據被存儲在一個DLL(服務器)上並由一個或多個客戶導出而使用,這些客戶能夠是應用程序或者是其它的DLL。DLL庫不一樣於靜態庫,在靜態庫狀況下,函數和數據被編譯進一個二進制文件(一般擴展名爲*.LIB), Visual C++的編譯器在處理程序代碼時將從靜態庫中恢復這些函數和數據並把他們和應用程序中的其餘模塊組合在一塊兒生成可執行文件。這個過程稱爲"靜態連接",此時由於應用程序所需的所有內容都是從庫中複製了出來,因此靜態庫自己並不須要與可執行文件一塊兒發行。
ios

在動態庫的狀況下,有兩個文件,一個是引入庫(.LIB)文件,一個是DLL文件,引入庫文件包含被DLL導出的函數的名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件連接到所須要使用的DLL文件,庫中的函數和數據並不複製到可執行文件中,所以在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中所要調用的函數的內存地址,這樣當一個或多個應用程序運行是再把程序代碼和被調用的函數代碼連接起來,從而節省了內存資源。從上面的說明能夠看出,DLL和.LIB文件必須隨應用程序一塊兒發行,不然應用程序將會產生錯誤。
編程

微軟的Visual C++支持三種DLL,它們分別是Non-MFC Dll(非MFC動態庫)、Regular Dll(常規DLL)、Extension Dll(擴展DLL)。Non-MFC DLL指的是不用MFC的類庫結構,直接用C語言寫的DLL,其導出的函數是標準的C接口,能被非MFC或MFC編寫的應用程序所調用。Regular DLL:和下述的Extension Dlls同樣,是用MFC類庫編寫的,它的一個明顯的特色是在源文件裏有一個繼承CWinApp的類(注意:此類DLL雖然從CWinApp派生,但沒有消息循環),被導出的函數是C函數、C++類或者C++成員函數(注意不要把術語C++類與MFC的微軟基礎C++類相混淆),調用常規DLL的應用程序沒必要是MFC應用程序,只要是能調用類C函數的應用程序就能夠,它們能夠是在Visual C++、Dephi、Visual Basic、Borland C等編譯環境下利用DLL開發應用程序。
windows

  • DLL的建立:

打開VS2013,選擇Win32:服務器

選擇DLL:函數

裏邊會自動爲你添加好幾個文件:測試

以及一個dllmain的格式,這裏面是,當加載一個DLL(ATTACH)或者釋放一個DLL(DETACH)等不一樣狀態發生時,所要執行的代碼(只不過下面的代碼是當四個狀態發生時什麼都不執行):字體

參數中,hMoudle是動態庫被調用時所傳遞來的一個指向本身的句柄(實際上,它是指向_DGROUP段的一個選擇符); ul_reason_for_call是一個說明動態庫被調緣由的標誌,當進程或線程裝入或卸載動態連接庫的時候,操做系統調用入口函數,並說明動態連接庫被調用的緣由,它全部的可能值爲:DLL_PROCESS_ATTACH: 進程被調用、DLL_THREAD_ATTACH: 線程被調用、DLL_PROCESS_DETACH: 進程被中止、DLL_THREAD_DETACH: 線程被中止;lpReserved爲保留參數。spa

咱們直接在testDLL.cpp中添加代碼,這裏保存的是DLL的導出函數:操作系統

extern "C" __declspec(dllexport) int add(int a, int b) 
{
    return (a + b);
}

extern "C" __declspec(dllexport) int sub(int a, int b)
{
    return (a - b);
}

編譯生成一個testDLL.dll.下面進行測試:

隱式鏈接:

#include <iostream>
#include <windows.h>

#pragma comment(lib,"testDLL.lib")
extern "C"_declspec(dllimport) int add(int a, int b);
extern "C"_declspec(dllimport) int sub(int a, int b);
int main()
{
    int nParam1 = 9;
    int nParam2 = 3;
    int nAdd = add(nParam1, nParam2);
    int nSub = sub(nParam1, nParam2);
    std::cout << nAdd << ":" << nSub << std::endl;
    system("pause");
    return 0;
}

顯示連接:

#include <iostream>
#include <windows.h>

int main()
{
    typedef int (*_pAdd)(int a, int b);
    typedef int (*_pSub)(int a, int b);
    HINSTANCE hDll = LoadLibrary("testDLL.dll");
    int nParam1 = 9;
    int nParam2 = 3;
    _pAdd pAdd = (_pAdd)GetProcAddress(hDll, "add");
    _pSub pSub = (_pSub)GetProcAddress(hDll, "sub");
    int nAdd = pAdd(nParam1, nParam2);
    int nSub = pSub(nParam1, nParam2);
    std::cout << nAdd << ":" << nSub << std::endl;
FreeLibrary(hDll); system(
"pause"); return 0; }

正確輸出結果:

 

參考:

http://www.cnblogs.com/daocaoren/archive/2012/05/30/2526495.html

相關文章
相關標籤/搜索