C 語言雖無原生閉包、高階函數支持,但通過函數指針與Wrapper 函數模式,可實現有限的函數式編程技巧。本文以線程池入口適配為例,展示如何用 Wrapper 解決函數簽名不匹配、參數綁定、類型安全等問題。
// 目標業務函數簽名 void my_task(void *arg); // 用戶定義 // pthread 要求簽名 void *(*start_routine)(void *); // 返回 void*,參數 void* // 直接強轉隱患: // 1. 返回值類型不匹配可能導致棧損壞 // 2. 無法綁定額外上下文參數 // 3. 類型安全全靠程序員自覺
// 包裝器:適配 void(*)(void) -> void*(*)(void*)
void *entry_wrapper(void (*entryPoint)(void)) {
entryPoint(); // 調用無參無返業務函數
return NULL; // 滿足 pthread 返回要求
}
// 線程創建封裝
int TaskCreate(void (*entryPoint)(void), ...) {
pthread_t tid;
pthread_attr_t attr;
// ... 屬性設置 ...
// 關鍵:傳遞 wrapper,並將 entryPoint 作為參數綁定
pthread_create(&tid, &attr, (void*(*)(void*))entry_wrapper, entryPoint);
// ...
}
若業務函數需要參數 void task(void *ctx),且創建時已知 ctx,可定義結構體綁定函數指針與上下文:
typedef struct {
void (*func)(void*);
void *ctx;
} TaskClosure;
void *closure_wrapper(void *arg) {
TaskClosure *c = (TaskClosure*)arg;
c->func(c->ctx);
free(c); // 由 wrapper 負責釋放綁定結構
return NULL;
}
int TaskCreateWithCtx(void (*func)(void*), void *ctx) {
TaskClosure *c = malloc(sizeof(TaskClosure));
c->func = func; c->ctx = ctx;
pthread_t tid;
pthread_create(&tid, NULL, closure_wrapper, c);
// ...
}
C 的 Wrapper 本質是手工構建閉包環境,每種簽名組合需寫專用 Wrapper,無法像 Lua 這樣動態生成:
-- Lua 真正的高階函數
function newCounter()
local i = 0
return function() -- 匿名函數捕獲 i
i = i + 1
return i
end
end
struct Closure { void (*fn)(void*); void *env; },所有高階操作操作此類型。map、filter、reduce 接受 Closure 參數,內部循環調用 fn(env)。auto void inner() { ... })可捕獲棧變量,但不可移植,慎用。Wrapper 函數是 C 語言函數式編程的**核心基建**:
雖無法達到動態語言的靈活度,但在系統編程、嵌入式、高性能場景下,這套「結構體+函數指針+Wrapper」模式已足夠構建清晰、安全、高效的回調與異步框架。