Embedding Lua: Possessing the Host Application
Lua was designed from the ground up to be embedded. Its C API is minimal yet powerful, allowing any C application to gain the flexibility of a scripting language without sacrificing performance.
Setting Up the Lua State
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void) {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
if (luaL_dofile(L, "config.lua") != LUA_OK) {
fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
The Stack: Lua's Communication Channel
All data exchange between C and Lua happens through a virtual stack. Understanding the stack is the single most important concept for Lua embedding:
// Push a global function onto the stack
lua_getglobal(L, "my_function");
// Push arguments
lua_pushinteger(L, 42);
lua_pushstring(L, "hello");
// Call: 2 arguments, 1 result
lua_pcall(L, 2, 1, 0);
// Get the result
int result = lua_tointeger(L, -1);
lua_pop(L, 1);
Exposing C Functions to Lua
static int l_add(lua_State *L) {
double a = luaL_checknumber(L, 1);
double b = luaL_checknumber(L, 2);
lua_pushnumber(L, a + b);
return 1; // Number of return values
}
// Register the function
lua_pushcfunction(L, l_add);
lua_setglobal(L, "add");
The Registry
The Lua registry is a special table accessible only from C. Use it to store references that persist across function calls without polluting the global namespace. Use luaL_ref() and luaL_unref() for safe reference management.
When you embed Lua, your C application gains a soul. It becomes configurable, extensible, and alive.
