環境: visual c++ 2003, windows
原文出處: codeguru
我正在學習dlls,談不上對其有什麼高屋建瓴的見解;本文只是(通過)編碼讓你看到並想知道**是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。
#ifndef _dll_tutorial_h_
#define _dll_tutorial_h_
#include
#if defined dll_export
#define decldir __declspec(dllexport)
#else
#define decldir __declspec(dllimport)
#endif
extern "c"
decldir int add( int a, int b );
decldir void function( void );
#endif
前面兩行指示編譯器只包含這個檔案一次。extern "c"告訴編譯器該部分可以在c/c++中使用。
在vc++中這裡有兩個方法來匯出函式:
1、使用__declspec,乙個microsoft定義的關鍵字。
2、建立乙個模組定義檔案(module-definition file即.def)。第一種方法稍稍比第二種方法簡單些,但兩種都工作得很好。
__declspec(dllexport)匯出函式符號到在你的dll中的乙個儲存類。當下面一行被定義時我定義decldir來執行這個函式,
#define dll_export
同時也匯入函式如果下面一行
#define dll_export
沒有在原始檔中出現。在此情況下,你將匯出函式add(int a, int b)和function()。
現在,你需要寫乙個將要稱為dlltutorial.cpp的原始檔。
#include
#include "dll_tutorial.h"
#define dll_export
extern "c"
decldir int add( int a, int b )
return( a + b );
decldir void function( void )
std::cout << "dll called!" << std::endl;
這裡你定義了(dll中的)所有函式。int add(int a, int b)只簡單地將兩個數相加而void function(void)只是在你的dll被呼叫時(將資訊)通知你。在我像你展示如何使用dll前,我想告訴你一些關於模組定義檔案(.def)的內容。
模組定義檔案(.def)
模組定義檔案是乙個有著.def副檔名的文字檔案。它被用於匯出乙個dll的函式,和__declspec(dllexport)很相似,但是.def檔案並不是microsoft定義的。乙個.def檔案中只有兩個必需的部分:library 和 exports。讓我們先看乙個基本的.def檔案稍後我將解析之。
library dll_tutorial
description "our ****** dll"
exports
add @1
function @2
現在你已經建立了你的dll,你需要學習如何在乙個應用程式中使用它了。當這個dll被生成後,它建立了乙個.dll檔案和乙個.lib檔案;這兩個都是你需要的。
隱式鏈結
這裡有兩個方法來載入乙個dll;乙個方法是捷徑另乙個則相比要複雜些。捷徑是只鏈結到你.lib 檔案並將.dll檔案置入你的新專案的路徑中去。因此,建立乙個新的空的win32控制台專案並新增乙個原始檔。將你做的dll放入你的新專案相同的目錄下。
#include
#include
int main()
function();
std::cout << add(32, 58) << "/n";
return(1);
#pragma comment(lib, "dlltutorial.lib")
請注意我讓編譯器來檢視我的dll資料夾已獲得.lib檔案同時讓它順便看下該目錄中的dll標頭檔案。如果你不想這麼做,你可以總是把他們放入你的新專案的目錄中並使用""(引號)而不是<>。這就是載入乙個dll的簡單方法。
顯示鏈結
難點的載入dll的方法是有稍微有點複雜的。你將需要函式指標和一些windows函式。但是,通過這種載入dlls的方法,你不需要dll的.lib或標頭檔案,而只需要dll。下面列出一些**,我稍後將解析之。
#include
#include
typedef int (*addfunc)(int,int);
typedef void (*functionfunc)();
int main()
addfunc _addfunc;
functionfunc _functionfunc;
hinstance hinstlibrary = loadlibrary("dll_tutorial.dll");
if (hinstlibrary == null)
freelibrary(hinstlibrary);
_addfunc = (addfunc)getprocaddress(hinstlibrary, "add");
_functionfunc = (functionfunc)getprocaddress(hinstlibrary, "function");
if ((_addfunc == null) || (_functionfunc == null))
freelibrary(hinstlibrary);
std::cout << _addfunc(23, 43) << std::endl;
_functionfunc();
std::cin.get();
freelibrary(hinstlibrary);
return(1);
首先你會注意到:這裡包括進了檔案「windows.h」同時移走了「dll_tutorial.h」。原因很簡單:因為windows.h包含了一些windows函式,當然你現在將只需要其中幾個而已。它也包含了一些將會用到的windows特定變數。你可以去掉dll的標頭檔案(dll_tutorial.h)因為-如我前面所說-當你使用這個方法載入dll時你並不需要它。
下面你會看到:以下面形式的一小塊古靈精怪的**:
typedef int (*addfunc)(int,int);
typedef void (*functionfunc)();
乙個hinstance是乙個windows資料型別:是乙個例項的控制代碼;在此情況下,這個例項將是這個dll。你可以通過使用函式loadlibrary()獲得dll的例項,它獲得乙個名稱作為引數。在呼叫loadlibrary函式後,你必需檢視一下函式返回是否成功。你可以通過檢查hinstance是否等於null(在windows.h中定義為0或windows.h包含的乙個標頭檔案)來檢視其是否成功。如果其等於null,該控制代碼將是無效的,並且你必需釋放這個庫。換句話說,你必需釋放dll獲得的記憶體。如果函式返回成功,你的hinstance就包含了指向dll的控制代碼。
一旦你獲得了指向dll的控制代碼,你現在可以從dll中重新獲得函式。為了這樣作,你必須使用函式getprocaddress(),它將dll的控制代碼(你可以使用hinstance)和函式的名稱作為引數。你可以讓函式指標獲得由getprocaddress()返回的值,同時你必需將getprocaddress()轉換為那個函式定義的函式指標。舉個例子,對於add()函式,你必需將getprocaddress()轉換為addfunc;這就是它知道引數及返回值的原因。現在,最好先確定函式指標是否等於null以及它們擁有dll的函式。這只是乙個簡單的if語句;如果其中乙個等於null,你必需如前所述釋放庫。
一旦函式指標擁有dll的函式,你現在就可以使用它們了,但是這裡有乙個需要注意的地方:你不能使用函式的實際名稱;你必需使用函式指標來呼叫它們。在那以後,所有你需要做的是釋放庫如此而已。
DLL初學者指南 非MFC
譯者 小刀人 dll project.rar dll project的源 及測試專案 原文出處 codeguru 我正在學習dlls,談不上對其有什麼高屋建瓴的見解 本文只是 通過 編碼讓你看到並想知道 是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。ifndef ...
DLL初學者指南 非MFC
我正在學習dlls,談不上對其有什麼高屋建瓴的見解 本文只是 通過 編碼讓你看到並想知道 是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。ifndef dll tutorial h define dll tutorial h include if defined d...
DLL初學者指南 非MFC
dll初學者指南 非mfc 我正在學習dlls,談不上對其有什麼高屋建瓴的見解 本文只是 通過 編碼讓你看到並想知道 是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。ifndef dll tutorial h define dll tutorial h includ...