用VC++建立支持VB進(jìn)行I/O端口操作的動(dòng)態(tài)鏈接庫(kù)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
摘 要:介紹了DLL的基本特點(diǎn),論述了用VC++5.0構(gòu)造輸入/輸出端口操作的DLL方法,舉例說(shuō)明了VB5.0對(duì)DLL的調(diào)用過(guò)程。
關(guān)鍵詞:DLL 端口操作 VC++ VB
Microsoft Windows已經(jīng)廣泛被人們所接受,人們?cè)絹?lái)越多地體會(huì)到了圖形用戶界面(GUI)給人們帶來(lái)的好處。Visual 就是一種Windows環(huán)境下最主要的可視漢化的高級(jí)編程語(yǔ)言。由于使用簡(jiǎn)單,功能強(qiáng)大,比直接用VC++編寫(xiě)Windows下的程序更為方便而倍受程序設(shè)計(jì)人員的青睞。但由于VB不能直接對(duì)寄存器進(jìn)行操作,沒(méi)有直接的輸入輸出端口操作語(yǔ)句,使得它在測(cè)控領(lǐng)域中的應(yīng)用有一定局限。而VC++同時(shí)具有匯編語(yǔ)言和高級(jí)語(yǔ)言的功能與特點(diǎn),如果利用VC++編制一個(gè)動(dòng)態(tài)鏈接庫(kù),庫(kù)中包含對(duì)輸入輸出端口的讀/寫(xiě)函數(shù),然后在VB程序中,通過(guò)聲明DLL中的函數(shù)并提供DLL路徑來(lái)調(diào)用這些函數(shù)完成控制行為,就可利用VB編寫(xiě)數(shù)據(jù)采集與控制程序,使VB的應(yīng)用更為廣泛。
1 動(dòng)態(tài)鏈接庫(kù)DLL
所為動(dòng)態(tài)鏈接庫(kù)( Library,簡(jiǎn)稱DLL),簡(jiǎn)單地說(shuō)就是一個(gè)可執(zhí)行模塊,模塊中包含了可以被應(yīng)用程序或DLL共享的例程和資源。與生成應(yīng)用程序鏈接的靜態(tài)庫(kù)不同的是,DLL與應(yīng)用程序是獨(dú)立分開(kāi)的,只在運(yùn)行時(shí)需要DLL的特定功能時(shí)才鏈接。此外,提供服務(wù)的機(jī)器代碼不是加進(jìn)應(yīng)用程序中,而是仍然作為動(dòng)態(tài)鏈接庫(kù)的一部分,可以把DLL看成一個(gè)黑盒子,能用于完成特定任務(wù)或返回特定數(shù)。DLL的優(yōu)點(diǎn)有:
(1)公用服務(wù) DLL提供的功能可以在不同時(shí)間或同一時(shí)間的多個(gè)不同應(yīng)用程序中共享。不同應(yīng)用程序調(diào)用DLL時(shí),盡管只有一份執(zhí)行代碼,但每個(gè)調(diào)用程序中函數(shù)使用的數(shù)據(jù)是分開(kāi)的。
(2)結(jié)構(gòu)緊湊 盡管當(dāng)前的編程趨勢(shì)是充分利用內(nèi)存降價(jià)和CPU增速的好處,但使用DLL仍然是減少執(zhí)行文件的有效方式。不管應(yīng)用程序如何編譯,也不管是編譯或解釋,DLL提供的函數(shù)都不放到應(yīng)用程序的.exe文件中,DLL提供的所有函數(shù)仍然留在DLL內(nèi),只有在需要時(shí)才調(diào)用。此外,由于在多個(gè)應(yīng)用程序共享服務(wù)時(shí)也仍然只有一份DLL,所以節(jié)省了復(fù)制代碼所需要的空間。
(3)易于修改,且執(zhí)行速度快。
2 用VC++5.0構(gòu)造DLL
若需要在DLL中構(gòu)造二個(gè)函數(shù)來(lái)完成輸入輸出端口的讀寫(xiě)功能,它們是:
8位端口讀函數(shù) int _input(int Num);
8位端口寫(xiě)函數(shù) int _(int Num,int Data);
為了用VC++5.0生成DLL,首先啟動(dòng)VC++5.0并在IDE中選擇File New Project標(biāo)簽,并選擇Win32 Library選項(xiàng),然后按照屏幕指示生成項(xiàng)目的基本文件。若輸入工程名為WST,則生成的基本文件有WST.CPP源文件、WST.H頭文件、WST.DEF定義文件。
(1)DEF文件
.DEF文件即定義文件,提供一列輸出函數(shù),使其在已編譯的DLL中以外部程序可以訪問(wèn)的形式出現(xiàn)。
盡管不用.DEF文件也可以編譯和鏈接DLL,并且不產(chǎn)生錯(cuò)誤報(bào)告,但VB程序調(diào)用時(shí),這個(gè)庫(kù)沒(méi)有可識(shí)別的進(jìn)入點(diǎn)。
WST.DEF文件很簡(jiǎn)單,由一列僅有函數(shù)名的輸出函數(shù)組成,也可以包括每個(gè)輸出函數(shù)的序號(hào)。標(biāo)準(zhǔn)的.DEF文件以Library和語(yǔ)句開(kāi)始。Library語(yǔ)句定義了DLL庫(kù)名,語(yǔ)句是可選的,用于輸入庫(kù)的用途說(shuō)明。然后是Exs語(yǔ)句,列出庫(kù)中的輸出函數(shù)名單,每個(gè)函數(shù)后面還可以加上序號(hào):
LIBRARY ?。ST"
′I/O and write Library′
EXPORTS
Port_input @1
Port_ @2
如果不顯示定義序號(hào),則DLL編譯和鏈接時(shí)會(huì)按順序指定缺省序號(hào)。
(2)頭文件
與可選的.DEF文件不同,.H文件是絕對(duì)需要的,其它要使用WST.DLL庫(kù)的C/C++應(yīng)用程序要用.H頭(在#include語(yǔ)句中)使應(yīng)用程序能訪問(wèn)輸出函數(shù),VB不用.H頭,但要求對(duì)應(yīng)的函數(shù)語(yǔ)句。
WST.H中的第一個(gè)項(xiàng)目為#define語(yǔ)句,將Export宏表示為:
Extern"C"_declspec(dllexport)
頭文件或.CPP源文件在編譯時(shí)出現(xiàn)EXPORT字樣時(shí),這個(gè)宏即展開(kāi)為如下完整的語(yǔ)句:
#define EXPORT extern"C"_declspec(dllexport)
在宏定義以后,需定義二個(gè)輸出函數(shù)如下:
EXPORT int CALLBACK port_input(int PortNum)
EXPORT int CALLBACK port_(int PortNum,int PortData);
這里,EXPORT表示了每個(gè)函數(shù)為外部函數(shù),變?cè)捎肅調(diào)用格式,庫(kù)采用輸出函數(shù)。CALLBACK宏已經(jīng)在VC++中定義,展開(kāi)為FARPASCAL,表示調(diào)用函數(shù)所需的處理過(guò)程。
(3)CPP文件
每個(gè)動(dòng)態(tài)鏈接庫(kù)都要有個(gè)入口點(diǎn),習(xí)慣上取名為DLLMain,就象Windows中執(zhí)行文件的入口點(diǎn)為WinMain,DOS中為Main一樣。同樣,調(diào)用DLLMain時(shí)的參數(shù)也是預(yù)定不變的。DLL的入口點(diǎn)函數(shù)在.CPP源文件中的最簡(jiǎn)單形式如下:
int WINAPI DLLMain(HINSTANCEhinstance,DWORD dwReason,PVOID pvReserved)
{
TRUE;
}
在DLLMain過(guò)程中,可以進(jìn)一步修改,例如可以對(duì)庫(kù)進(jìn)行某種特殊的初始化。一般來(lái)說(shuō),在DLLMain過(guò)程中只要返回True向系統(tǒng)表示DLL加載正確即可。一旦提供了DLLMain過(guò)程,就可以編譯和鏈接源文件,生成有效的DLL庫(kù)了。當(dāng)然這個(gè)庫(kù)還沒(méi)有任何功能,下一步要加進(jìn)功能,至少提供一個(gè)輸出過(guò)程。DLL過(guò)程與任何C/C++過(guò)程差不多,只是多了個(gè)EXPORT指定。源文件中要重復(fù).H頭中的過(guò)程定義,但這時(shí)不用終止分號(hào),并具有變量類型標(biāo)識(shí)符和變量名:
EXPORT int CALLBACK port_intput(int PortNum)
{
_inp(PortNum);
}
EXPORT int CALLBACK port_output(int PortNum,int PortData){
_outp(PortNum,PortData);
0;
}
在寫(xiě)完上面二個(gè)文件后就可以編譯、鏈接該工程,生成WST.DLL文件
3 VB5.0調(diào)用DLL函數(shù)的方法
由于DLL中的函數(shù)對(duì)于VB5.0程序來(lái)講是外部函數(shù),因此用戶須向VB5.0提供要使用的DLL函數(shù)的有關(guān)信息。這種提供信息的方法就是聲明。VB5.0就是通過(guò)這種聲明訪問(wèn)DLL的。其編譯器根據(jù)這種聲明確定參數(shù)、類型檢查,而且在運(yùn)行期間,VB5.0也將依據(jù)聲明將參數(shù)壓棧。一旦在窗體聲明部分或在共用模塊中聲明了DLL過(guò)程,用戶就可以象使用VB5.0關(guān)鍵字或是用戶自己定義的VB5.0過(guò)程一樣,很方便地使用DLL中的函數(shù)。
在主窗體中WST.DLL輸出函數(shù)聲明方法如下:
Private Declare Function port_input Lib"D:\fort\WST.DLL"Alias"#1"(ByvalPortNum As Integer)As Integer
Private Declare Function port_output Lib"D:\fort\WST.DLLl"Alias"#2"(ByvalPortNum%,Byval PortData%)AsInteger
進(jìn)行如上聲明之后,在VB5.0窗體程序中,就可編寫(xiě)對(duì)端口進(jìn)行操作的采集與控制程序。端口讀/寫(xiě)操作語(yǔ)句示范如下:
port_output(&h280,&h0A)?。亩丝?80H輸出數(shù)據(jù)0AH
Value=port_input(&H280) ?。亩丝?80H讀入數(shù)據(jù)賦給變量Value
由于這種方法簡(jiǎn)單可行,無(wú)需編寫(xiě)復(fù)雜的設(shè)備驅(qū)動(dòng)程序即可實(shí)現(xiàn)VB5.0對(duì)端口的讀寫(xiě)操作,因此對(duì)利用VB5.0編寫(xiě)測(cè)控程序的開(kāi)發(fā)人員來(lái)說(shuō),不失為一種方便的途徑。