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

COM 元件載入替代方案:導出 C 風格工廠函數 (GdiexCreate)

     編輯:關於C++

問題背景

標準 COM 透過 CoCreateInstance 建立物件,需註冊表、CLSID、IClassFactory 機制。純 C 專案或不想依賴 COM 執行期時,需更簡潔的載入方式。

解決方案:DLL 導出工廠函數

參考 DirectX Direct3DCreate9 模式,在 COM DLL 內部實作並導出:

// COM 內部實作
HRESULT WINAPI GdiexCreate(LPVOID* lplpGdiex) {
    ISaveDDCtrl* pCtrl = nullptr;
    HRESULT hr = CoCreateInstance(CLSID_SaveDDCtl, NULL, CLSCTX_SERVER,
                                  IID_ISaveDDCtl, (void**)&pCtrl);
    if (FAILED(hr)) {
        MessageBox(NULL, L"GdiexCreate Failed!", L"gdiexPS", MB_OK|MB_ICONSTOP);
        return hr;
    }
    *lplpGdiex = pCtrl; // 直接回傳介面指標
    return S_OK;
}

// 釋放對應函數
HRESULT WINAPI GdiexFree(LPVOID pCtrl) {
    if (pCtrl) static_cast(pCtrl)->Release();
    return S_OK;
}

模組定義檔

; Gdiex.def
EXPORTS
    DllCanUnloadNow PRIVATE
    DllGetClassObject PRIVATE
    DllRegisterServer PRIVATE
    DllUnregisterServer PRIVATE
    GdiexCreate
    GdiexFree

使用者端調用 (C/C++ 通用)

#include "gdiex.h" // 宣告 GdiexCreate/GdiexFree
#pragma comment(lib, "gdiex.lib")

ISaveDDCtl* pCtl = nullptr;
CoInitialize(NULL);
HRESULT hr = GdiexCreate((LPVOID*)&pCtl);
if (SUCCEEDED(hr)) {
    // 使用 pCtl...
    GdiexFree(pCtl);
}
CoUninitialize();

優缺點分析

優點缺點
無需註冊表/CLSID,部署簡單 (XCopy deploy)失去 COM 定位/版本管理/進程外激活能力
C/C++ 直接調用,無互操作開銷需手動管理 DLL 載入/卸載 (LoadLibrary/FreeLibrary)
介面指標直接回傳,型別安全單一 DLL 只能導出一組工廠,擴充性弱
適合插件架構、輕量級元件跨語言 (C#/VB) 需 P/Invoke,不如標準 COM 友善

適用場景

  • 內部專案、綠色軟體、無註冊表權限環境。
  • 插件系統:主程式 LoadLibrary → GetProcAddress("PluginCreate") → 取得介面。
  • 需支援 C 語言呼叫的 COM 封裝層。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved