Creating C closures from Lua closures

Lua devs turn functions into C magic, commenters yell “just use a table”

TLDR: A Lua-to-C callback trick wowed devs, but the crowd pushed back: use simple tables, Lua’s own memory allocator, or GCC’s nested functions instead of fancy hacks. It matters because making Windows features work in Lua is powerful—if you don’t overcomplicate it.

A developer showed how to turn Lua functions (which remember their outside variables) into C callbacks (functions that C can call later) to make Windows features work from Lua. Cool, right? The crowd loved the idea—but immediately split into camps. One camp, led by widdershins, dropped the hot take: skip any assembly wizardry and “just return a table” that packs the function pointer and its index. Translation: keep it simple, ditch the global variable and cleverness. Another camp side-eyed the memory moves. “Why VirtualAlloc?” asked shakna, waving Lua’s built‑in allocator like a flag. Meanwhile, ufo wondered if GCC’s “nested functions” could be the secret shortcut, hinting at compiler tricks to make this cleaner without custom code.

Meta‑commentary added spice: psychoslave asked why closures are suddenly everywhere, linking to fresh hype threads here and here, and even dropped the “Knuth boy/man test” as a wink at over‑engineering. The vibe? C meet Lua is fun, but the community is roasting anything that smells like unnecessary complexity. Jokes flew about “callback cosplay” and “closure cults,” while pragmatists demanded tables, userdata, and fewer global variables. It’s a nerd soap opera: pointers, opinions, and plenty of clapbacks.

Key Points

  • The article aims to bridge the Windows C API to Lua by creating C callbacks from Lua functions.
  • Lua 5.4 closures capture outer variables (“up values”), enabling stateful Lua functions used in callbacks.
  • C lacks closures and typically passes state via void* pointers to callbacks; an example demonstrates this pattern.
  • A naive implementation stores a Lua function in the Lua registry and exposes a C shim (REAL_CALLBACK) via light userdata.
  • The Lua C API stack is used to push arguments, call the Lua function, and convert the result back to a C int.

Hottest takes

"This doesn't seem like something that should require generating assembly to solve." — widdershins
"Why VirtualAlloc?" — shakna
"I wonder if there would be a way to piggyback on top of GCC's nested function extension." — ufo
Made with <3 by @siedrix and @shesho from CDMX. Powered by Forge&Hive.