国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開(kāi)通VIP
如何編寫DLL文件(開(kāi)發(fā)環(huán)境VS2005)

如何編寫DLL文件(開(kāi)發(fā)環(huán)境VS2005)

動(dòng)態(tài)鏈接庫(kù)

 

在Windows 應(yīng)用程序中使用動(dòng)態(tài)鏈接庫(kù)有很多的好處。最主要的一點(diǎn)說(shuō)是它可以使得多個(gè)應(yīng)用程序共享一段代碼,從而可以大幅度的降低應(yīng)用程序的資源開(kāi)銷,同時(shí)很縮小了應(yīng)用程序的最終執(zhí)行代碼的大小。此外,通過(guò)使用動(dòng)態(tài)鏈接庫(kù),我們可以把一些常規(guī)的例程獨(dú)立出來(lái),有效的避免了不必要的重復(fù)開(kāi)發(fā),并且,由于應(yīng)用程序使用了動(dòng)態(tài)鏈接的方式,還可以在不需重新改寫甚至編譯應(yīng)用程序的基礎(chǔ)上更新應(yīng)用程序的某些組件。

 

DLL分三種,包括:非MFC DLL、靜態(tài)鏈接到MFC的常規(guī)DLL、動(dòng)態(tài)鏈接到MFC的常規(guī)DLL、MFC擴(kuò)展DLL,

1.非MFC DLL(non-MFC DLL)內(nèi)部不使用MFC,調(diào)用非MFC DLL提供的導(dǎo)出函數(shù)的可執(zhí)行程序可以使用MFC,也可以不使用MFC。一般來(lái)說(shuō),非MFC DLL的導(dǎo)出函數(shù)都使用標(biāo)準(zhǔn)的C接口(standard C interface)。

2.其余三種DLL的內(nèi)部都使用了MFC。顧名思義,靜態(tài)鏈接到MFC的常規(guī)DLL(regular DLL statically linking to MFC)和動(dòng)態(tài)鏈接到MFC的常規(guī)DLL(regular DLL dynamically linking to MFC)的區(qū)別在于一個(gè)使用的是MFC的靜態(tài)鏈接庫(kù),而另一個(gè)使用的是MFC的DLL。這和一般的MFC應(yīng)用程序的情況是很類似的。

3.MFC 擴(kuò)展DLL一般用來(lái)提供派生于MFC的可重用的類,以擴(kuò)展已有的MFC類庫(kù)的功能。MFC擴(kuò)展DLL使用MFC的動(dòng)態(tài)鏈接版本。只有使用MFC動(dòng)態(tài)鏈接的可執(zhí)行程序(無(wú)論是EXE還是DLL)才能訪問(wèn)MFC擴(kuò)展DLL。MFC擴(kuò)展DLL的另一個(gè)有用的功能是它可以在應(yīng)用程序和它所加載的MFC擴(kuò)展DLL之間傳遞MFC和MFC派生對(duì)象的指針。在其它情況下,這樣做是可能導(dǎo)致問(wèn)題的。

 

如何選擇所應(yīng)該使用的DLL的類型呢?我們可以從以下幾個(gè)方面來(lái)考慮:

1.相比使用了MFC的DLL而言,非MFC DLL顯得更為短小精悍。因此,如果DLL不需要使用MFC,那么使用非MFC DLL是一個(gè)很好的選擇,它將顯著地節(jié)省磁盤和內(nèi)存空間。同時(shí),無(wú)論應(yīng)用程序是否使用了MFC,都可以調(diào)用非MFC DLL中所導(dǎo)出的函數(shù)。

2.如果需要?jiǎng)?chuàng)建使用了MFC的DLL,并希望MFC和非MFC應(yīng)用程序都能使用所創(chuàng)建的DLL,那么可以選擇的范圍包括靜態(tài)鏈接到MFC的常規(guī)DLL和動(dòng)態(tài)鏈接到MFC的常規(guī)DLL。動(dòng)態(tài)鏈接到MFC的常規(guī)DLL比較短小,因此可以節(jié)省磁盤和內(nèi)存,但是,在分發(fā)動(dòng)態(tài)鏈接到MFC的常規(guī)DLL時(shí),必須同時(shí)分發(fā)MFC的支持DLL,如MFCx0.DLL和MSVCRT.DLL等。而使用靜態(tài)鏈接到MFC的常規(guī)DLL則不存在這種問(wèn)題。

3.如果希望在DLL中實(shí)現(xiàn)從MFC派生的可重用的類,或者是希望在應(yīng)用程序和DLL之間傳遞MFC的派生對(duì)象時(shí),必須選擇MFC擴(kuò)展DLL。

 

創(chuàng)建和使用動(dòng)態(tài)鏈接庫(kù)

DLL文件和EXE文件都屬于可執(zhí)行文件,不同的是DLL文件包括了一個(gè)導(dǎo)出表,導(dǎo)出表中給出了可以從DLL中導(dǎo)出的所有函數(shù)的名字。外部可執(zhí)行程序只能訪問(wèn)包括在DLL的導(dǎo)出表中的函數(shù),DLL中的其它函數(shù)是私有的,不能為外部可執(zhí)行程序所訪問(wèn)??梢允褂肰isual C++提供的DUMPBIN實(shí)用程序(可以在DevStudio\VC\bin目錄下找到這個(gè)工具)來(lái)查看一個(gè)DLL文件的結(jié)構(gòu)。舉一個(gè)例子,如果需要查看DLL文件msgbox.dll的導(dǎo)出表,可以在命令提示符下鍵入下面的命令:

>dumpbin /exports msgbox.dll

運(yùn)行結(jié)果如下:

Microsoft (R) COFF Binary File Dumper Version 5.00.7022

Copyright (C) Microsoft Corp 1992-1997. All rights reserved.

Dump of file msgbox.dll

File Type: DLL

Section contains the following Exports for MSGBOX.dll

0 characteristics

351643C3 time date stamp Mon Mar 23 19:13:07 1998

0.00 version

1 ordinal base

1 number of functions

1 number of names

ordinal hint name

1 0 MsgBox (00001000)

Summary

7000 .data

1000 .idata

2000 .rdata

2000 .reloc

17000 .text

由上面的結(jié)果得知,msgbox.dll中僅包括了一個(gè)導(dǎo)出函數(shù)MsgBox()。

注意:

僅僅知道導(dǎo)出函數(shù)的名稱并不足以從DLL中導(dǎo)出該函數(shù)。若在應(yīng)用程序中使用顯式鏈接(link explicitly),至少還應(yīng)該知道導(dǎo)出函數(shù)的返回值的類型以及所傳遞給導(dǎo)出函數(shù)的參數(shù)的個(gè)數(shù)、順序和類型;若使用隱含鏈接(link implicitly),必須有包括導(dǎo)出函數(shù)(或類)的定義的頭文件(.H文件)和引入庫(kù)(import library,.LIB文件),這些文件是由DLL的創(chuàng)建者所提供的。

或者用depends工具也可以,而且此工具為可視化界面,使用更方便。

 

DLL中導(dǎo)出函數(shù)有兩種方法:

在創(chuàng)建DLL時(shí)使用模塊定義(module DEFinition,.DEF)文件。

在定義函數(shù)時(shí)使用關(guān)鍵字_declspec(dllexport)。

 

下面我們通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)分別說(shuō)明兩種方法的使用。在這個(gè)例子中,我們將創(chuàng)建一個(gè)只包括一個(gè)函數(shù)MsgBox()的DLL,函數(shù)MsgBox()用來(lái)顯示一個(gè)消息框,它和Win32 API函數(shù)MessageBox()的功能是一樣,只不過(guò)在函數(shù)MsgBox()中,不需要指定消息的父窗口,而且可以缺省其它所有的參數(shù)。

 

(1) 使用模塊定義文件

模塊定義文件是一個(gè)文本文件,它包括了一系列的模塊語(yǔ)句,這些語(yǔ)句用來(lái)描述DLL的各種屬性,典型的,模塊語(yǔ)句定義了DLL中所導(dǎo)出的函數(shù)的名稱和順序值。

在講解模塊定義文件之前,我們先創(chuàng)建一個(gè)Win32 Dynamic-Link Library工程。

1. 在Microsoft Developer Studio中選擇File菜單下的New命令,在Projects選項(xiàng)卡中選擇Win32 Dynamic-Link Library,并為工程取一個(gè)名字,如msgbox。單擊OK后,Visual C++創(chuàng)建一個(gè)Win32 DLL的空白工程,必須手動(dòng)的將所需要的文件添加到工程中。

2. 單擊Project菜單下的Add To Project子菜單下的New命令,在Files選項(xiàng)卡中選擇Text File,在File文本框中輸入DEF文件名,如msgbox.def。

3. 雙擊Workspace窗口的FileView選項(xiàng)卡中的msgbox.def節(jié)點(diǎn),在msgbox.def文件中輸入下面的內(nèi)容:

LIBRARY MSGBOX

EXPORTS

MsgBox @1

在DEF文件中的第一條語(yǔ)句必須是LIBRARY語(yǔ)句,該語(yǔ)句表明該DEF文件屬于一個(gè)DLL,在LIBRARY之后是DLL的名稱,這個(gè)名稱在鏈接時(shí)將放到DLL的引入庫(kù)中。EXPORTS 語(yǔ)句下列出了DLL的所有導(dǎo)出函數(shù)以及它們的順序值。函數(shù)的順序值不是必須的,在指定導(dǎo)出函數(shù)的順序值時(shí),我們?cè)诤瘮?shù)名后跟上一個(gè)@符號(hào)和一個(gè)數(shù)字,該數(shù)字即導(dǎo)出函數(shù)的順序值。如果在DEF中指定了順序值,它必須不小于1,且不大于DLL中所有導(dǎo)出函數(shù)的數(shù)目。

 

注意:對(duì)于VS2005還要有以下設(shè)置,選擇 工程 > 屬性中的鏈接器,然后找到"輸入"這一項(xiàng). 在 "模塊定義文件" 中輸入 msgbox.def.

4. 下一步是向工程中添加一個(gè)頭文件,它定義了DLL中的函數(shù)的返回值的類型和參數(shù)的個(gè)數(shù)、順序和類型。

單擊菜單項(xiàng)Project|Add To Project|New...,在Files選項(xiàng)卡下選擇C/C++ Header File,在File文本框中指定頭文件名,如msgbox.h(可以省略后綴名.h)。

在頭文件中輸入如下的內(nèi)容:

#include<Windows.h>

extern "C" int MsgBox(

                              LPCTSTR lpText=L"雖然這個(gè)例子有一些幼稚,但它工作得非常的好!", // 消息框的文本

                              LPCTSTR lpCaption=L"一個(gè)簡(jiǎn)單的例子",  // 消息框的標(biāo)題

                              UINT uType=MB_OK); // 消息框的樣式

請(qǐng)注意函數(shù)定義前的關(guān)鍵字extern "C",這是由于我們使用了C++語(yǔ)言來(lái)開(kāi)發(fā)DLL,為了使C語(yǔ)言模塊能夠訪問(wèn)該導(dǎo)出函數(shù),我們應(yīng)該使用C鏈接來(lái)代替C++鏈接。否則,C++編譯器將使用C++的類型安全命名和調(diào)用協(xié)議,這在使用C調(diào)用該函數(shù)時(shí)就會(huì)遇上問(wèn)題。在本例中并不需要考慮到這個(gè)問(wèn)題,因?yàn)槲覀冊(cè)陂_(kāi)發(fā)DLL和應(yīng)用程序時(shí)都是使用C ++,但我們?nèi)匀粡?qiáng)烈建議使用extern "C",以保證在使用C編寫的程序調(diào)用該DLL的導(dǎo)出函數(shù)不會(huì)遇上麻煩。

5. 下面要做的事是向工程中添加一個(gè)C++源文件,在該文件中實(shí)現(xiàn)函數(shù)MsgBox()。

仿照上面的過(guò)程,單擊菜單項(xiàng)Project|Add To Project|New...,在Files選項(xiàng)卡下選擇C++ Source File,在File文本框中指定源文件名,如msgbox.cpp。

在msgbox.cpp文件中添加如下的代碼:

#include "msgbox.h"

int MsgBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType)

{

      return MessageBox(NULL,lpText,lpCaption,uType);

}

編譯該工程,在Debug目錄下生成文件msgbox.lib和msgbox.dll。

(2) 使用關(guān)鍵字_declspec(dllexport)

從DLL中導(dǎo)出文件的另一種方法是在定義函數(shù)時(shí)使用_declspec(dllexport)關(guān)鍵字。這種方法不需要使用DEF文件。

仍使用前面的例子,在工程中刪除msgbox.def文件,將msgbox.h文件修改如下:

#include<Windows.h>

extern "C" _declspec(dllexport) int MsgBox( // 消息框的文本

                              LPCTSTR lpText=L"雖然這個(gè)例子有一些幼稚,但它工作得非常的好!", // 消息框的標(biāo)題

                              LPCTSTR lpCaption=L"一個(gè)簡(jiǎn)單的例子", // 消息框的樣式

                              UINT uType=MB_OK);

msgbox.cpp文件并不需要做任何修改,重新編譯該工程,在Debug目錄下仍生成兩個(gè)文件msgbox.lib和msgbox.dll。

使用__declspec(dllexport)從DLL中導(dǎo)出類的語(yǔ)法如下:

class __declspec(dllexport) CDemoClass

{

...

}

注意:

如果在使用__declspec(dllexport)的同時(shí)指定了調(diào)用協(xié)議關(guān)鍵字,則必須將__declspec(dllexport)關(guān)鍵字放在調(diào)用協(xié)議關(guān)鍵字的左邊。如:int __declspec(dllexport) __cdacl MyFunc();

 

如何從這兩種導(dǎo)出函數(shù)的方法中作出選擇,可以從下面的幾個(gè)方面考慮:

如果需要使用導(dǎo)出順序值(export ordinal value),那么應(yīng)該使用DEF文件來(lái)導(dǎo)出函數(shù)。只在使用DEF文件導(dǎo)出函數(shù)才能指定導(dǎo)出函數(shù)的順序值。使用順序值的一個(gè)好處是當(dāng)向DLL中添加新的函數(shù)時(shí),只要新的導(dǎo)出函數(shù)的順序值大于原有的導(dǎo)出函數(shù),就沒(méi)有必要重新鏈接使用隱含鏈接的應(yīng)用程序。相反,如果使用__declspec (dllexport)來(lái)導(dǎo)出函數(shù),如果向DLL中添加了新的函數(shù),使用隱含鏈接的應(yīng)用程序有可以需要重新編譯和鏈接。

使用DEF文件來(lái)導(dǎo)出函數(shù),可以創(chuàng)建具有NONAME屬性的DLL。具有NONAME屬性的DLL在導(dǎo)出表中僅包含了導(dǎo)出函數(shù)的順序值,這種類型的DLL在包括有大量的導(dǎo)出函數(shù)時(shí),其文件長(zhǎng)度要小于通常的DLL。

使用DEF文件從C++文件導(dǎo)出函數(shù),應(yīng)該在定義函數(shù)時(shí)使用extern "C"或者在DEF文件中指定導(dǎo)出函數(shù)的decorated name。否則,由于編譯器所產(chǎn)生的decorated name是基于特定編譯器的,鏈接到該DLL的應(yīng)用程序也必須使用創(chuàng)建DLL的同一版本的Visual C++來(lái)編譯和鏈接。

由于使用__declspec(dllexport)關(guān)鍵字導(dǎo)出函數(shù)不需要編寫DEF文件,因此,如果編寫的DLL只供自己使用,使用__declspec(dllexport)較為簡(jiǎn)單。

 

鏈接應(yīng)用程序到DLL

同樣,鏈接應(yīng)用程序到DLL也有兩種方法:隱含鏈接、顯式鏈接

 (1) 使用隱含鏈接

在使用隱含鏈接除了需要相應(yīng)的DLL文件外,還必須具備如下的條件:一個(gè)包括導(dǎo)出的函數(shù)或C++類的頭文件、一個(gè)輸入庫(kù)文件(.LIB文件)

將三個(gè)文件放入程序的目錄中,在程序中的項(xiàng)目——屬性——配置屬性——鏈接器——輸入,在附加依賴項(xiàng)中將LIB文件名寫上(也可在文件頭加入#pragma comment(lib,"msgbox.lib")),包含所創(chuàng)建的DLL:msgbox.dll所對(duì)應(yīng)的頭文件msgbox.h如下:

extern "C" __declspec(dllimport)int MsgBox(

                              LPCTSTR lpText=L"雖然這個(gè)例子有一些幼稚,但它工作得非常的好!",// 消息框的文本

                              LPCTSTR lpCaption=L"一個(gè)簡(jiǎn)單的例子", // 消息框的標(biāo)題

                              UINT uType=MB_OK);  // 消息框的樣式

需要注意的是,這個(gè)msgbox.h文件和創(chuàng)建DLL時(shí)所使用msgbox.h是不同的,唯一的差別在于,創(chuàng)建DLL時(shí)的msgbox.h中使用的是 __declspec(dllexport)關(guān)鍵字,而供應(yīng)用程序所使用的msgbox.h中使用的是__declspec(dllimport)關(guān)鍵字。無(wú)論創(chuàng)建DLL時(shí)使用的是DEF文件還是__declspec(dllexport)關(guān)鍵字,均可使用__declspec(dllimport)關(guān)鍵字從DLL中引入函數(shù)。引入函數(shù)時(shí)也可以省略__declspec(dllimport)關(guān)鍵字,但是使用它可以使編譯器生成效率更高的代碼。

注意:

如果需要引入的是DLL中的公用數(shù)據(jù)和對(duì)象,則必須使用__declspec(dllimport)關(guān)鍵字。

如果DLL使用的是def文件,要?jiǎng)h除TestDll.h文件中關(guān)鍵字extern "C"。

 

現(xiàn)在使用Microsoft Developer Studio創(chuàng)建一個(gè)Win32 Application工程,命名為tester。向工程中添加一個(gè)C++源文件,如tester.cpp。在tester.cpp文件中輸入下面的代碼:

#include "msgbox.h" // 應(yīng)將msgbox.h文件拷貝到工程tester的目錄下。

int WINAPI WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

return MsgBox();

}

在上面的代碼中,MsgBox()函數(shù)的所有參數(shù)都使用了缺省值。

(2) 使用動(dòng)態(tài)鏈接

如果只有DLL文件,只能采用動(dòng)態(tài)鏈接的方式了。需要用到三個(gè)函數(shù):

          LoadLibrary(L"###.dll");    此處的L,是表示UNICODE,在VS2005中,對(duì)字符的處理時(shí)默認(rèn)是按照UNICODE方式處理的。

          GetProcAddress(hDllLib,"函數(shù)名"); 這個(gè)是用于返回所需要調(diào)用的DLL中的函數(shù)的地址。一般在此前需要聲明一個(gè)與要調(diào)用的函數(shù)原型相同的函數(shù)指針,用于接收此函數(shù)返回的地址指針。

          FreeLibrary(hDllLib);   因?yàn)镈LL是動(dòng)態(tài)加載的,在用完后一定要釋放資源。

例如:

typedef int(*lpmsgbox)(LPCTSTR , LPCTSTR , UINT );

      HINSTANCE hDLL;

      lpmsgbox msgbox;

      hDLL=LoadLibrary(L"msgbox.dll");//加載動(dòng)態(tài)鏈接庫(kù)msgbox.dll文件;

      msgbox=(lpmsgbox)GetProcAddress(hDLL,"MsgBox");

      msgbox(L"Hello",L"Hello",MB_OK);

      FreeLibrary(hDLL);//卸載msgbox.dll文件;

 在上例中使用類型定義關(guān)鍵字typedef,定義指向和DLL中相同的函數(shù)原型指針,然后通過(guò)LoadLibray()將DLL加載到當(dāng)前的應(yīng)用程序中并返回當(dāng)前DLL文件的句柄,然后通過(guò)GetProcAddress()函數(shù)獲取導(dǎo)入到應(yīng)用程序中的函數(shù)指針,函數(shù)調(diào)用完畢后,使用FreeLibrary()卸載DLL文件。在編譯程序之前,首先要將DLL文件拷貝到工程所在的目錄或Windows系統(tǒng)目錄下。

 使用顯式鏈接應(yīng)用程序編譯時(shí)不需要使用相應(yīng)的Lib文件。另外,使用GetProcAddress()函數(shù)時(shí),可以利用MAKEINTRESOURCE()函數(shù)直接使用DLL中函數(shù)出現(xiàn)的順序號(hào),如將GetProcAddress(hDLL,"MsgBox")改為GetProcAddress(hDLL, MAKEINTRESOURCE(1))(函數(shù)MsgBox ()在DLL中的順序號(hào)是1),這樣調(diào)用DLL中的函數(shù)速度很快,但是要記住函數(shù)的使用序號(hào),否則會(huì)發(fā)生錯(cuò)誤。

最后建議大家進(jìn)行隱士鏈接dll。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
VC 動(dòng)態(tài)鏈接庫(kù)(DLL)編程深入淺出
使用c 開(kāi)發(fā)excel插件 (第3章動(dòng)態(tài)鏈接庫(kù)(dynamic
使用 __declspec(dllexport) 從 DLL 導(dǎo)出
DLL(Dynamic Link Libraries)
動(dòng)態(tài)鏈接庫(kù)創(chuàng)建與使用
MFC DLL向?qū)?摘) - 醬壇子 - C++博客
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服