DLL初學者指南

2021-07-05 16:47:57 字數 3897 閱讀 7230

我正在學習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初學者指南

這裡有兩個方法來載入乙個dll 乙個方法是捷徑另乙個則相比要複雜些。捷徑是只鏈結到你.lib 檔案並將.dll檔案置入你的新專案的路徑中去。因此,建立乙個新的空的win32控制台專案並新增乙個原始檔。將你做的dll放入你的新專案相同的目錄下。include include declspec dlli...

DLL初學者指南

dll初學者指南 dll project的源 及測試專案 原文出處 codeguru 我正在學習dlls,談不上對其有什麼高屋建瓴的見解 本文只是 通過 編碼讓你看到並想知道 是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。ifndef dll tutorial h...

DLL初學者指南 非MFC

譯者 小刀人 dll project.rar dll project的源 及測試專案 原文出處 codeguru 我正在學習dlls,談不上對其有什麼高屋建瓴的見解 本文只是 通過 編碼讓你看到並想知道 是如何執行的。在本文中,我假定你知道如何使用你的編譯器特性,比如設定目錄路徑等等。ifndef ...