本文實戰演示如何使用 ATL 實作支援多個自訂介面的 COM 組件,並闡述符合 COM 規範的介面升級策略(不可修改已發布介面,需新增介面擴充功能)。
IMathe2)提供,舊用戶繼續使用 IMathe,新用戶享受完整功能。使用 ATL 精靈建立自訂介面 IMathe,含 Add(long, long, long*) 整數加法函式。必須為自訂介面,非雙重介面。
interface IMathe : IUnknown {
[helpstring("method Add")] HRESULT Add([in] long n1, [in] long n2, [out,retval] long *pnVal);
};
coclass Mathe {
[default] interface IMathe;
};
關鍵點:UUID 為介面唯一識別(IID),coclass 區塊宣告元件支援的介面清單,[default] 標示預設提供 IUnknown 的介面。
[object, uuid(072EA6CB-...), helpstring("IStr Interface"), pointer_default(unique)]
interface IStr : IUnknown {
// 暫無函式,後續添加
};
同步更新 coclass 區塊:
coclass Mathe {
[default] interface IMathe;
interface IStr; // 新增介面聲明
};
class ATL_NO_VTABLE CMathe :
public CComObjectRootEx,
public CComCoClass,
public IMathe,
public IStr // 新增基底介面
{
BEGIN_COM_MAP(CMathe)
COM_INTERFACE_ENTRY(IMathe)
COM_INTERFACE_ENTRY(IStr) // 註冊介面入口
END_COM_MAP()
};
於 IStr 添加字串連接函式:
HRESULT Cat([in] BSTR s1, [in] BSTR s2, [out,retval] BSTR *psVal);
組件已發布,需新增乘法 Mul()。不可修改 IMathe,解決方案:
IMathe2 : IUnknown,包含 Add() 與新增的 Mul()。interface IMathe2;。public IMathe2 並加入 COM_INTERFACE_ENTRY(IMathe2)。IMathe2::Mul(),Add() 可轉呼叫既有實作或重新實作。此策略確保二進位相容:舊用戶透過 QueryInterface(IID_IMathe) 繼續工作,新用戶透過 QueryInterface(IID_IMathe2) 獲得擴充功能。
COM 介面不變原則:一旦發布,介面定義凍結。功能擴充唯一正途——新增介面。此為 COM 元件長期演進的基石。