回調函數是一種強大的編程模式:當特定事件發生時,系統或其他模組會自動調用你預先定義的函數。在 Windows 程式設計中,Hook 回調(如 MouseProc、GetMsgProc)、EnumWindows、DrawState 等都大量使用回調。本文不介紹系統級回調,而是分享在 VC 與 Delphi 混合開發中實現自定義回調的實戰經驗。
專案採用 VC 編寫 DLL 執行耗時的異步任務,完成後需通知 Delphi 主程式處理後續邏輯。最初嘗試同步物件、記憶體映射、訊息傳遞等方式,後靈機一想:若在應用程式端預先定義好處理函數,DLL 直接呼叫該函數地址即可。這就是回調函數的雛形。
統一使用 __stdcall 呼叫慣例,確保 C++ 與 Pascal 編譯器參數壓棧、返回值處理一致。
// VC 版
typedef int (WINAPI *PFCALLBACK)(int Param1, int Param2);
// Delphi 版
type
PFCALLBACK = function(Param1: Integer; Param2: Integer): Integer; stdcall;
全域函數或類的靜態成員函數皆可。
// VC 版
int WINAPI CBFunc(int Param1, int Param2);
// Delphi 版
function CBFunc(Param1, Param2: Integer): Integer; stdcall;
PFCALLBACK gCallBack = nullptr;
void WINAPI TestCallBack(PFCALLBACK Func) {
if (Func == nullptr) return;
gCallBack = Func;
DWORD ThreadID;
HANDLE hThread = CreateThread(nullptr, 0, ThreadProc, nullptr, 0, &ThreadID);
}
// 工作執行緒:模擬耗時操作,完成後呼叫回調
ULONG WINAPI ThreadProc(LPVOID) {
// ... 延時模擬工作 ...
if (gCallBack) gCallBack(Step, 1); // 觸發回調
return 0;
}
// VC 應用程式
int WINAPI CBFunc(int Param1, int Param2) {
int res = Param1 + Param2;
MessageBox(nullptr, L"回調被觸發", L"測試", MB_OK);
return res;
}
// Delphi 應用程式
function CBFunc(Param1, Param2: Integer): Integer;
begin
Result := Param1 + Param2;
Form1.Edit1.Text := IntToStr(Result);
end;
回調模式讓模組間耦合度極低:核心邏輯專注於自身業務,擴充功能僅透過函數指標介面交付外部處理。適用於異步、事件驅動、插件架構等場景。本質上只是將函數視為可傳遞的位址,卻能帶來極大的靈活性。