Creating C closures from Lua closures When I set out to bridge the entire Windows C API to Lua, one of the most interesting and fun challenges I had was to create C callbacks from Lua functions. Without this, a significant portion of the API would be useless, such as WNDPROC. Brief primer on Lua closures For those unfamiliar with Lua 5.4, it has semantics perhaps 90% similar to JavaScript. In this case, that includes closures and lexical scoping. That is, outer variables are "enclosed around" when a new function is created that makes use of them. In Lua, these are called "up values", because they come from "up" in a higher lexical scope. local a = 1 local f = function(b) return a + b end print(f(2)) -- prints 3 Brief primer on C "closures" The brutally but beautifully minimalistic language of C has no concept of closures at all. But it does have functions and pointers to raw memory, which are enough to work with. Therefore it's conventional to manually pass data through to callback functions via pointer to appropriate memory. The following trivial example shows the basic concept at work. The outer caller and inner callback pass around a pointer and are aware of its true type, but the middle function is unaware, and simply passes it through as a void *ctx. int cb(void *ctx, int b) { int a = *(int*)ctx; return a + b; } int add(void *a, int b, int (*f)(void *ctx)) { return f(a, b); } int main() { int a = 1; add(&a, 2, &cb); } Note: the C expressions cb and &cb both produce an address (in fact, the same address), but I explicitly used &cb here to make it more clear that it's a normal C address, in order to tie better into what we're going to do later. The ideal bridging API This is the Lua API that I settled on: local a = 1 local lpfnWndProc = WNDPROC(function(hwnd, umsg, wparam, lparam) if umsg == WM_KEYDOWN then print(a) end return DefWindowProc(hwnd, umsg, wparam, lparam) end) That is, you pass a Lua function to another Lua function that represents the C callback typ...
First seen: 2025-12-16 07:00
Last seen: 2025-12-16 16:02