在使用 Visual C++ 配合 ATL 開發 COM 組件時,編譯器會自動產生一個副檔名為 .tlh 的類型庫標頭檔。這個檔案包含了從類型庫轉換而來的 C++ 定義,是理解 COM 介面、類別與智慧型指標的關鍵。本文將以 ValidateCreditCardServer.tlh 為例,逐步剖析其結構與內容。
// Created by Microsoft (R) C/C++ Compiler Version 12.00.8168.0
// c:\vctest\vccomproj\debug\ValidateCreditCardServer.tlh
// C++ source equivalent of Win32 type library ..\ValidateCreditCardServer\Debug\ValidateCreditCardServer.dll
// compiler-generated file created 12/19/03 at 03:29:03 - DO NOT EDIT!
#pragma once
#pragma pack(push, 8)
#include <comdef.h>
namespace VALIDATECREDITCARDSERVERLib {
// Forward references and typedefs
struct /* coclass */ ValidateCard;
struct __declspec(uuid("b1d1c73c-e340-4fdc-8734-92ecec64dc4e"))
/* dual interface */ IValidateCard;
// Smart pointer typedef declarations
_COM_SMARTPTR_TYPEDEF(IValidateCard, __uuidof(IValidateCard));
// Type library items
struct __declspec(uuid("c79635d2-7b86-4b20-a83c-0565dca54c3c")) ValidateCard;
// [ default ] interface IValidateCard
struct __declspec(uuid("b1d1c73c-e340-4fdc-8734-92ecec64dc4e")) IValidateCard : IDispatch {
// Wrapper methods for error-handling
long ValidateCreditCard(_bstr_t bstrCCNo, _bstr_t bstrCCType);
HRESULT LuhnCheck(_bstr_t bstrCCNo, _bstr_t bstrCCType);
HRESULT LengthCheck(_bstr_t bstrCCNo, _bstr_t bstrCCType);
HRESULT PrefixCheck(_bstr_t bstrCCNo, _bstr_t bstrCCType);
// Raw methods provided by interface
virtual HRESULT __stdcall raw_ValidateCreditCard(BSTR bstrCCNo, BSTR bstrCCType, long * val) = 0;
virtual HRESULT __stdcall raw_LuhnCheck(BSTR bstrCCNo, BSTR bstrCCType) = 0;
virtual HRESULT __stdcall raw_LengthCheck(BSTR bstrCCNo, BSTR bstrCCType) = 0;
virtual HRESULT __stdcall raw_PrefixCheck(BSTR bstrCCNo, BSTR bstrCCType) = 0;
};
}
#pragma pack(pop)
VALIDATECREDITCARDSERVERLib 命名空間封裝了整個類型庫的定義。前向宣告 ValidateCard(coclass)與 IValidateCard(dual interface)讓編譯器在完整定義出現前就能識別這些型別。
_COM_SMARTPTR_TYPEDEF(IValidateCard, __uuidof(IValidateCard)) 會展開為 _com_ptr_t<_com_IIID,提供參考計數自動管理的智慧型指標 IValidateCardPtr,簡化介面指標的釋放與查詢。
c79635d2-7b86-4b20-a83c-0565dca54c3c 對應 ValidateCard 組件類別。b1d1c73c-e340-4fdc-8734-92ecec64dc4e 對應 IValidateCard 介面。IValidateCard 繼承自 IDispatch,提供四個高層包裝方法(回傳 long 或 HRESULT,參數為 _bstr_t)以及四個對應的原始虛擬函數(參數為 BSTR,輸出參數為指標)。包裝方法內部會呼叫原始方法並處理錯誤,適合 C++ 程式碼直接使用;原始方法則是給跨語言或底層呼叫用。
IValidateCardPtr)管理介面生命週期,避免記憶體洩漏。raw_* 方法,但需自行檢查 HRESULT。透過閱讀編譯器產生的 .tlh,我們能清楚掌握 COM 組件的類別識別碼、介面定義、方法簽章與智慧型指標型別,這對除錯、跨模組呼叫以及撰寫高品質 ATL 程式碼都極有幫助。