回呼函式對初學者常顯神秘。本文解析何謂回呼、為何使用、適用場景,並提供完整動態庫排序回呼實作範例。
簡單說:透過函式指標呼叫的函式。若將函式位址作為參數傳遞給另一函式,並在該函式內透過指標調用,即為回呼。
SetTimer(hwnd, id, interval, TimerProc):計時器到期呼叫 TimerProc 或發送 WM_TIMER。EnumWindows(EnumWindowsProc, lParam):枚舉頂層視窗,對每個視窗呼叫回呼,回傳 FALSE 停止枚舉。回呼源自 C 語言。現代 C++ 應優先使用:
僅在介接 C API、現有回呼介面、或極度效能敏感無虛函式開銷時使用函式指標回呼。
typedef int (__stdcall *CompareFunction)(const BYTE*, const BYTE*);
#define DLLDIR __declspec(dllexport)
DLLDIR void __stdcall BubbleSort(BYTE* array, int size, int elemSize, CompareFunction cmp);
DLLDIR void __stdcall QuickSort(BYTE* array, int size, int elemSize, CompareFunction cmp);
#include "SortDLL.h"
void __stdcall BubbleSort(BYTE* array, int size, int elemSize, CompareFunction cmp) {
for (int i = 0; i < size-1; i++)
for (int j = 0; j < size-i-1; j++)
if (cmp(array + j*elemSize, array + (j+1)*elemSize) > 0)
swap_bytes(array + j*elemSize, array + (j+1)*elemSize, elemSize);
}
void __stdcall QuickSort(BYTE* array, int size, int elemSize, CompareFunction cmp) {
// 快速排序實作,同樣呼叫 cmp 比較元素
}
回呼函式 cmp(a, b) 必須回傳:
-1:a < b(a 排前)0:a == b1:a > b(a 排後)
#include "SortDLL.h"
int __stdcall CompareInt(const BYTE* a, const BYTE* b) {
int ia = *reinterpret_cast(a);
int ib = *reinterpret_cast(b);
return (ia < ib) ? -1 : (ia > ib) ? 1 : 0;
}
int main() {
int arr[] = {5, 2, 9, 1, 3};
BubbleSort(reinterpret_cast(arr), 5, sizeof(int), CompareInt);
// arr 現為 {1,2,3,5,9}
return 0;
}
__stdcall 統一呼叫慣例,避免 DLL 邊界堆疊破壞。std::function + Lambda,獲得型別安全與捕獲上下文能力。