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