透過使用型別庫提高VB呼叫DLL函式的效能 (轉)
本文始發於水木清華BBS(smth.org),轉載請保留有關資訊,謝謝!
透過使用型別庫提高VBDLL的
RoachCock@smth
to:chen3feng@163.com">mailto:chen3feng@163.com,
,
.com">chen3fengx@hotmail.com
VB雖然是個很好玩的東西,但是自身功能有限,限制了VB在某些方面的應用.
MS提供了兩種兩種方式來增強VB的功能,一種是呼叫COM,另一種就是呼叫Dll函式
說到呼叫COM,大家都很熟悉,在Project->Reference或者Project->Component
選單彈出對話方塊中選擇需要的型別庫或者,就可以把它加入Project.
呼叫Dll函式也很簡單,需要使用Declare函式宣告先:
Declare Function MessageBox Lib "user32" Alias "MessageBoxA" ( _
ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, _
ByVal wType As Long) As Long
然後就可以像內部函式一樣呼叫了:
MessageBox Me.hWnd, "hehe", "Test", 0
下面我分析一下在上面的呼叫過程中,到底發生了什麼.
我們知道,VB的字串是Unicode字串,每個字元佔兩個位元組,但是翻開WinUser.h
我們可以看到MessageBoxA的真實定義,
WINUSER int WINAPI MessageBoxA(HWND hWnd ,LPCSTR lpText,
LPCSTR lpCaption, UINT uType);
LPCSTR是一個const char *型別,是一個指向單位元組ANSI字串的指標,
把呼叫這個函式的Project編譯成exe,,用VC帶的depends.exe看到底到如何引用的函式
竟然除了MSVBVM60.dll.什麼也沒有!
這中間到底發生了什麼呢?
透過反跟蹤生成的程式碼可以知道,VB要先呼叫__vbaStrToAnsi把字串轉化成ANSI字
符串,再把得到的Ansi字串傳給一個內部函式(一般稱為DllFunctionCall),這個函式再
真正去呼叫Dll中的函式
如果函式呼叫後還要使用傳給Dll函式的字串引數的話(比如GetWindowText什麼的),就
更復雜了,VB會呼叫一個叫做__vbaStrToUnicode的函式,把引數轉化成Unicode,再
傳遞給函式.
也許你會說,MessageBox並不會改變傳給它的引數,根本不需要在轉換成Unicode.是的,你
知道,我也知道但是VB編譯器不知道,宣告函式的Declare語句裡可沒指出引數傳遞的方向.
也許你會說,我的只在WinNT,,下執行,他們內部都是用的Unicode字串
,我直接呼叫Unicode版本的MessageBoxW不是更好嗎?
對不起,由於只基本完全實現了ANSI函式,而基本沒有實現Unicode版本的函式,而W
inNT則兩者都實現了.為了照顧Win9x,VB把宣告語句中的String都當成ANSI字串.
//需要Unicode,卻依賴於ANSI操作,可憐的VB!
由此,我想你已經看到了Declare語句到底在那裡影響了.好吧.讓我們開始新的歷程
!
[idl語言和型別庫]
型別庫對VB程式設計師來說應該很熟悉了,這裡我只簡單的介紹一下idl語言.
IDL (Interface Definition Language)是主要用於COM和的一種介面定義語言,用
來描述各種介面,只是一種描述語言而不是一種語言.IDL的風格類似於C.IDL語言不
但可以描述更多的資料型別還可以描述引數的傳遞方向,因此上面的兩個問題都不再是問
題了.
一般使用IDL語言都是為了描述COM介面等.其實IDL也一樣可以用於描述全域性函式.讓我們
看一個例子,
還舉那個MessageBox吧
開啟VC6,新建一個Utitity Project,名字就叫MyTlb吧
新建一個文字檔案,名字還叫MyTlb.idl吧,輸入以下內容:
[ // 方括號表示一個idl屬性,用來描述一些額外的資訊,要和下面的東西連起來看.
uuid("9F7B1BC0-28C6-11d7-8F56-0080C8F0A08C") // 用VC帶的GUidgen生成一個新的
GUID,別和我的這個一樣哦
]
library MyLib // library說明了一個型別庫,MyLib是庫的名字
{
[
dllname("user32.dll") file://因為下面的模組描述了函式,所以需要dll庫的名字
]
module Test // test是模組的名字
{
[
entry("MessageBoxW") // entry屬性表明下面函式的入口,可以是函式的名字或者序號
]
long __stdcall Message(HWND hWnd, [in]LPCWSTR msg, [in]LPCWSTR title, long
flags);
// __stdcall表示函式的呼叫約定,後面是參數列
// [in]表示引數只傳入,[out][in]表示引數只傳入,[in,out]表示既傳入又傳出,類推
// 對於簡單的值型別,可以省略,預設就是[in]了
// 再有函式可以接著寫
}
}
按F7編譯,一個嶄新的型別庫誕生了! // btw,直接呼叫midl編譯器也可以,不過我覺得很
多人都不喜歡命令列了, :)
把它引入我們的工程,不需要宣告直接就可以呼叫MessageBox了.反彙編程式碼,可以發現沒
有多餘的轉換.
而且因為明確的指出了引數傳遞方向,不需要假設引數會被改變,生成的程式碼會更高效,
避免了DllFunctionCall的開支,更節省時間.
其他函式也可以一樣處理, 98 Re Kit帶了一個Win.tlb,包含了常用Wind
ows型別,常量,以及API的定義,非常方便,完全可以擺脫Declared語句的使用.可以在
()搜到.
不過這個tlb是ANSI版本的(嘛),如果需要Unicode版本的,就得自己寫idl檔案編譯
了
至於其他不帶型別庫的的DLL函式,你可以找這上面的例子自己來,函式數目比較多的情況
下完全劃的來.
祝各位假期程式設計愉快!
--
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-996974/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 透過例子學習Lua(4)--函式的呼叫(轉)函式
- VB動態呼叫外部函式的方法 (轉)函式
- VB6.0中透過MSChart控制元件呼叫資料庫 (轉)控制元件資料庫
- 呼叫建構函式進行型別轉換函式型別
- 走近VB.Net(二) 再談函式呼叫 (轉)函式
- 透過 CancellationToken 提高 Web 效能Web
- 函式庫呼叫和系統呼叫的區別函式
- 透過例子學習Lua(7)--呼叫C/C++函式(轉)C++函式
- Python透過函式名呼叫函式的幾種場景Python函式
- VB中呼叫WebService上的函式的方法Web函式
- 再談在VB中呼叫VC++開發的DLL (轉)C++
- 詳解 Qt 呼叫 DLL功能函式QT函式
- 單據型別引數設定增加自定義引數並透過BOS標準函式呼叫型別函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(1)函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(2)函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(4)函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(5)函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(6)函式
- ZT - 怎樣提高呼叫數學函式的程式的效能(7)函式
- vb如何使用ftp函式,vb如何使用ftp函式要知道這些FTP函式
- VB呼叫API函式使視窗保持在最上層 (轉)API函式
- 呼叫類庫函式的簡單加密(轉的)函式加密
- 使用條件型別實現TypeScript中的函式過載型別TypeScript函式
- 移除函式呼叫能有更好的效能函式
- NX二次開發-C#使用DllImport呼叫libufun.dll裡的UF函式(反編譯.net.dll)呼叫loop等UF函式C#Import函式編譯OOP
- 請別誤用 TypeScript 過載函式型別TypeScript函式型別
- C語言中庫函式呼叫幾例(轉)C語言函式
- 透過對TOS的最佳化來提高防火牆的整體效能(轉)防火牆
- 如何使用 Java 程式透過 SAP Java Connector 呼叫 ABAP 系統的函式試讀版Java函式
- 使用VB6.0設計ActiveX DLL事件 (轉)事件
- 利用動態建立自動化介面實現VB的函式指標呼叫 (轉)函式指標
- 建構函式定義的隱式型別轉換函式型別
- php呼叫mysql儲存過程和函式的方法(轉)PHPMySql儲存過程函式
- 一個簡單函式—Number型別轉換Date型別函式型別
- 透過開發VB外掛來擴充套件VB應用 (轉)套件
- 把匿名函式賦值給變數,透過變數來呼叫函式賦值變數
- c# 呼叫 C++ dll 傳入傳出型別對應說明(轉)C#C++型別
- TypeScript 函式型別TypeScript函式型別