首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

純 C++ 實作進程內 COM 組件:零 ATL/MFC 依賴的類別工廠與介面實作

     編輯:關於VC++

不依賴 ATL/MFC,以純 C++ 實作標準進程內(In-Process)COM 伺服器,深入理解 IClassFactory、IUnknown、DllGetClassObject 等核心機制。適用於 Shell Extension 等輕量級 COM 元件開發。

四大實作階段

1. 定義介面與 GUID(Header)

#include <comdef.h>
// CLSID
__declspec(selectany) GUID CLSID_Mine = {0xdc186800, 0x657f, 0x11d4, {0xb0,0xb5,0x0,0x50,0xba,0xbf,0xc9,0x4}};
// 介面 IID 與方法
__interface __declspec(uuid("F614FB00-6702-11d4-B0B7-0050BABFC904"))
ImyInterface : public IUnknown {
    STDMETHOD(Square)(long* pVal) PURE;
    STDMETHOD(Cube)(long* pVal) PURE;
};

2. 介面實作類別

class CmyInterface : public CComBase<>, public InterfaceImpl<ImyInterface> {
public:
    STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
    STDMETHOD(Square)(long* pVal);
    STDMETHOD(Cube)(long* pVal);
};

STDMETHODIMP CmyInterface::QueryInterface(REFIID riid, LPVOID* ppv) {
    *ppv = NULL;
    if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, __uuidof(ImyInterface))) {
        *ppv = (ImyInterface*)this; _AddRef(); return S_OK;
    }
    return E_NOINTERFACE;
}
STDMETHODIMP CmyInterface::Square(long* pVal) { *pVal = (*pVal) * (*pVal); return S_OK; }
STDMETHODIMP CmyInterface::Cube(long* pVal)  { *pVal = (*pVal) * (*pVal) * (*pVal); return S_OK; }

3. 類別工廠實作

template <class T> class CMultiCreator { // 多例工廠
public: T* CreateObject() { return new T; }
};

class CClassFactory : public CComBase<>, public InterfaceImpl<IClassFactory>, public CMultiCreator<CmyInterface> {
public:
    STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppv);
    STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObj);
    STDMETHODIMP LockServer(BOOL) { return S_OK; }
};

STDMETHODIMP CClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObj) {
    *ppvObj = NULL;
    if (pUnkOuter) return CLASS_E_NOAGGREGATION;
    m_pObj = CreateObject(); // CmyInterface 實例
    if (!m_pObj) return E_OUTOFMEMORY;
    HRESULT hr = m_pObj->QueryInterface(riid, ppvObj);
    if (FAILED(hr)) delete m_pObj;
    return hr;
}

4. 匯出 DllGetClassObject

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppvOut) {
    *ppvOut = NULL;
    if (IsEqualIID(rclsid, CLSID_Mine)) {
        CClassFactory* pcf = new CClassFactory;
        return pcf->QueryInterface(riid, ppvOut);
    }
    return CLASS_E_CLASSNOTAVAILABLE;
}

用戶端呼叫

ImyInterface* pMine = NULL;
CoCreateInstance(CLSID_Mine, NULL, CLSCTX_INPROC_SERVER,
    __uuidof(ImyInterface), (void**)&pMine);
long val = 5; pMine->Square(&val); // val = 25
pMine->Cube(&val);  // val = 125
pMine->Release();

關鍵點總結

  • CComBase 提供參考計數(_AddRef/_Release)。
  • InterfaceImpl<T> 實作介面查詢轉發。
  • 多重介面繼承可支援單一物件多介面。
  • 註冊表需寫入 HKCR\CLSID\{CLSID}\InprocServer32 指向 DLL 路徑。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved