現代應用程式常需支援第三方擴充功能(外掛/插件)。本文示範如何設計一套基於 DLL 的外掛架構:定義標準介面、主程式動態載入/管理外掛、外掛實作介面並匯出建立函式,達成「主程式不修改即可新增功能」的目標。
Plug_CreateObject 工廠函式。LoadLibrary/GetProcAddress 載入 DLL、呼叫工廠函式取得介面指標、管理外掛生命週期。#pragma once
#include
class CPlugBase
{
public:
virtual ~CPlugBase() {}
// 取得外掛圖示(主程式顯示於工具列/選單)
virtual HICON GetIcon() = 0;
// 外掛核心功能
virtual void Hello(int k) = 0;
// 釋放資源(主程式卸載時呼叫)
virtual void Release() = 0;
};
// 外掛工廠函式原型
typedef BOOL (*PFN_CREATE_PLUG)(void** ppObj);
#include "PlugBase.h"
class CMyPlug : public CPlugBase
{
public:
HICON GetIcon() override { return LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); }
void Hello(int k) override { MessageBox(NULL, L"Hello from Plug 1!", L"Plug", MB_OK); }
void Release() override { delete this; }
};
extern "C" __declspec(dllexport) BOOL Plug_CreateObject(void** ppObj)
{
*ppObj = new CMyPlug();
return *ppObj != NULL;
}
#include "PlugBase.h"
#include
#include
#include
struct PlugInfo
{
HMODULE hDll;
CPlugBase* pPlug;
};
std::vector g_plugs;
BOOL LoadPlug(const wchar_t* dllPath)
{
HMODULE hDll = LoadLibrary(dllPath);
if (!hDll) return FALSE;
auto pfnCreate = (PFN_CREATE_PLUG)GetProcAddress(hDll, "Plug_CreateObject");
if (!pfnCreate) { FreeLibrary(hDll); return FALSE; }
void* pObj = nullptr;
if (!pfnCreate(&pObj) || !pObj) { FreeLibrary(hDll); return FALSE; }
CPlugBase* pPlug = static_cast(pObj);
g_plugs.push_back({ hDll, pPlug });
return TRUE;
}
void UnloadAllPlugs()
{
for (auto& info : g_plugs)
{
if (info.pPlug) info.pPlug->Release();
if (info.hDll) FreeLibrary(info.hDll);
}
g_plugs.clear();
}
// 介面調用範例
void InvokePlugHello(int index, int param)
{
if (index >= 0 && index < g_plugs.size() && g_plugs[index].pPlug)
g_plugs[index].pPlug->Hello(param);
}
主程式啟動時讀取設定檔(Registry/INI/JSON),載入記錄的 DLL 路徑;使用者透過 UI 新增外掛時,將路徑寫入設定檔,下次自動載入。
| 主題 | 說明 |
|---|---|
| 版本相容 | 介面加入版本號,Plug_CreateObject 回傳版本資訊,主程式檢查相容性。 |
| 錯誤處理 | 載入失敗時記錄日誌、顯示友善訊息、不讓單一外掛 crash 整個主程式(可考慮隔離進程)。 |
| 資源管理 | 外掛自行管理 GDI 物件、執行緒、記憶體,Release() 確保清理。 |
| 安全性 | 簽章驗證 DLL、沙箱機制、限制外掛權限。 |
| 跨語言 | 介面改用 C 風格函式指標或 COM,支援 C#、Python 等語言撰寫外掛。 |
DLL 外掛架構核心在於介面契約與動態載入。主程式僅依賴抽象介面,外掛獨立編譯部署,實現開放封閉原則(OCP)。掌握此模式,即可為應用程式賦予無限擴充潛力。