因為這是 Visual Basic 的第一個版次,因此提供了 Declare 陳述式做為利用以其他語言撰寫之 DLL
函數的方式,如 C。但是 Declare 陳述式並不完美,同時您也必須對 DLL 有相當程度的熟悉 (如同您熟悉 Visual Basic
程式碼的程度一般)。型別程式庫在呼叫匯出的 C 函數方面可提供更友善的方式來使用 Visual Basic。
本文將告訴您如何在建置
DLL 時建立型別程式庫,以及如何從 Visual Basic 參照該程式庫。
型別程式庫是在自動化中使用的複合文件檔案 (.tlb
檔)。型別程式庫包含自動化伺服器向其用戶端公開的類別、物件、模組及介面的重要資訊。好處是,伺服器不需要具備自動化支援特性就可利用型別程式庫。事實上,大部分的
C DLL 都不是自動化伺服器,它們只需將其函數宣告為型別程式庫中模組的成員。這樣自動化用戶端 (如 Visual Basic)
就可讀取並繫結此資訊,就如同它處理任何物件一樣。因為 Visual Basic 可以完成所有的工作,因此不需要 Declare 陳述式或花費精力來記住常數。
為 DLL 建立型別程式庫有許多優點。最重要的是它可以增強型別的安全性。同時您也會獲得更好的效能,因為 Visual Basic
會使用之前的繫結自動繫結到您的函數。相反的,所有 Declare 陳述式都是晚期繫結。此外,您還可以更好地控制將 DLL 提供給Visual Basic
程式設計人員的方式。型別程式庫可讓您為函數及參數提供 Visual Basic 易記名稱,還有列舉及使用者定義型別 (UDT) 等其他有用內容。
目前來說,型別程式庫是使用以介面定義語言 (IDL) 或物件描述語言 (ODL) 撰寫的指令碼來建立的。然後會使用隨附於 Visual
Studio 的 MkTypLib.EXE 或 MIDL.EXE 來編譯這些指令碼。Visual C++
會分擔一些建立型別程式庫的工作,因為在您編譯專案時,與 DLL 專案關聯的任何 ODL 檔案都將自動使用 MIDL 進行編譯。
逐步範例 - 建立 DLL 及型別程式庫
- 開啟 Visual C++ 5.0 並選取 [檔案|新增]。在 [專案] 索引標籤中選取 [Win32
動態連結程式庫] 並將專案命名為 "TLBSamp"。
- 再次選取 [檔案|新增]。在 [檔案] 索引標籤中,選取 [C++ 原始程式檔]、將檔案命名為
"TLBSamp.c",再按一下 [確定]。
- 再次重複步驟 2,並在這一次選取 [文字檔案] 做為檔案類型。分別將檔案命名為 "TLBSamp.def" 及
"TLBSamp.odl"。
- 接下來,將下列程式碼加入 TLBSamp.c:
#include <windows.h>
// MyDll_ReverseString -- Reverses the characters of a given string
void __stdcall MyDll_ReverseString(LPSTR lpString)
{
_strrev(lpString);
}
// MyDLL_Rotate -- Returns bit rotation of 32-bit integer value
int __stdcall MyDll_Rotate(int nVal, int nDirect, short iNumBits)
{
int nRet = 0;
if((iNumBits < 1) || (iNumBits > 31))
return nRet;
switch(nDirect)
{
case 0:
// Rotate nVal left by iNumBits
nRet = (((nVal) << (iNumBits)) |
((nVal) >> (32-(iNumBits))));
break;
case 1:
// Rotate nVal right by iNumBits
nRet = (((nVal) >> (iNumBits)) |
((nVal) << (32-(iNumBits))));
break;
}
return nRet;
}
- 如果要讓函數可匯出,將下列程式碼加入 TLBSamp.def:
LIBRARY TLBSamp
DESCRIPTION 'Microsoft KB Sample DLL'
EXPORTS
MyDll_ReverseString
MyDll_Rotate
- 新增下列程式碼到 TLBSamp.odl 從而在型別程式庫中宣告函數:
// This is the type library for TLBSamp.dll
[
// Use GUIDGEN.EXE to create the UUID that uniquely identifies
// this library on the user's system. NOTE: This must be done!!
uuid(F1B9E420-F306-11d1-996A-92FF02C40D32),
// This helpstring defines how the library will appear in the
// References dialog of VB.
helpstring("KB Sample: Make your C DLL More Accessible"),
// Assume standard English locale.
lcid(0x0409),
// Assign a version number to keep track of changes.
version(1.0)
]
library TLBSample
{
// Define an Enumeration to use in one of our functions.
typedef enum tagRotateDirection
{
tlbRotateLeft=0,
tlbRotateRight=1
}RotateDirection;
// Now define the module that will "declare" your C functions.
[
helpstring("Sample functions exported by TLibSamp.dll"),
version(1.0),
// Give the name of your DLL here.
dllname("TLBSamp.dll")
]
module MyDllFunctions
{
[
// Add a description for your function that the developer can
// read in the VB Object Browser.
helpstring("Returns the reverse of a given string."),
// Specify the actual DLL entry point for the function. Notice
// the entry field is like the Alias keyword in a VB Declare
// statement -- it allows you to specify a more friendly name
// for your exported functions.
entry("MyDll_ReverseString")
]
// The [in], [out], and [in, out] keywords tell the Automation
// client which direction parameters need to be passed. Some
// calls can be optimized if a function only needs a parameter
// to be passed one-way.
void __stdcall ReverseString([in, out] LPSTR sMyString);
[
helpstring("Rotates a Long value in the given direction."),
entry("MyDll_Rotate")
]
// Besides specifying more friendly names, you can specify a more
// friendly type for a parameter. Notice the Direction parameter
// has been declared with our enumeration. This gives the VB
// developer easy access to our constant values.
int __stdcall BitRotate([in] int Value,
[in] RotateDirection Direction,
[in] short Bits);
} // End of Module
}; // End of Library
- 透過選擇 [建置] 功能表的 [全部重建] 來編譯 DLL 及型別程式庫。完成時,將新的 DLL
(TLBSamp.dll) 複製到您的 Visual Basic 目錄,進行測試。
注意:為方便起見,您可能希望將型別程式庫作為資源包括到 DLL 中。這樣就可以不需要向 Visual Basic
程式開發人員分散單獨的 TLB 檔案。
如果要將程式庫加入做為資源,請完成下列步驟:
- 選取 [檔案|新增]。在 [檔案] 索引標籤中,選取 [文字檔案]、將檔案命名為 "TLBSamp.rc",再按一下
[確定]。
- 在出現的文字視窗中新增下行:
1 typelib TLBSamp.tlb - 儲存檔案並重新編譯 DLL。完成時,將新的 DLL (TLBSamp.dll) 複製到您的 Visual Basic
目錄,進行測試:如果出現提示,請覆寫前一個檔案。
逐步範例 - Visual Basic 測試應用程式
- 如果要測試您的 DLL 及型別程式庫,請開啟 Visual Basic 5.0 並建立新的標準專案。根據預設會建立
Form1。
- 選取 [專案] 功能表中的 [參考] 來呼叫 [參考] 對話方塊,然後按一下 [瀏覽] 尋找新的型別程式庫 (或
DLL,如果您已將程式庫加入為資源)。找到之後按一下 [確定]。Visual Basic
將在您首次參考程式庫時自動登錄程式庫。請確定您已在參考清單中勾選您的程式庫 (「KB 範例:讓 C DLL 更容易存取」),然後關閉對話方塊。
- 按下 F2 鍵以開? [物件瀏覽器]。請注意您的程式庫 (TLBSamp) 已加入 Visual Basic
專案中,且可以呼叫原始 Visual Basic 函數的方式來呼叫您的函數。Visual Basic 甚至可以在開發人員向 BitRotate 函數中輸入
Direction 參數時下拉列舉清單。
- 將 CommandButton 加入至 Form1,然後將下列程式碼加入按鈕的 Click 事件:
Private Sub Command1_Click()
Dim n1 As Long, n2 As Long, nTmp As Long
Dim sTest As String, sMsg As String
sTest = "Hello World!"
n1 = 100
ReverseString sTest
sMsg = sTest & " | "
ReverseString sTest
sMsg = sMsg & sTest & vbCrLf
nTmp = BitRotate(n1, tlbRotateLeft, 2)
n2 = BitRotate(nTmp, tlbRotateRight, 2)
sMsg = sMsg & Str$(n1) & " : " & Str$(nTmp) & " : " & Str$(n2)
MsgBox sMsg
End Sub
- 現在按下 F5 鍵就可以在 IDE 中執行 vb5allB 專案。
注意:如果您收到錯誤訊息,可能是因為 Visual Basic 找不到您的 DLL。請確定在執行應用程式之前,您已將 DLL 複製到 Visual Basic
目錄或系統路徑。
如需 ODL 或 IDL 結構的詳細資訊,請參閱下列 Microsoft Developer Network
(MSDN) 資料庫中的文章:
標題:型別程式庫及物件描述語言
標題:介面定義及型別程式庫
如需詳細資訊,請參閱「Microsoft 知識庫」中的下列文件:
143258?
(http://support.microsoft.com/kb/143258/
)
How To Create Constants and DLL Declarations in a Type Library
122285?
(http://support.microsoft.com/kb/122285/
)
: How To Add Type Libraries as Resources to .dll and .exe Files
142840?
(http://support.microsoft.com/kb/142840/
)
INFO: Visual Basic Requirements for Exported DLL Functions
(c) Microsoft Corporation 1998. All Rights Reserved.由
Microsoft Corporation,Richard R. Taylor 提供。