Embedding Lua in C
Prerequisites: Environments and sandboxing
Lua was designed to be embedded. A C (or C++) program creates a Lua state, runs scripts, and exchanges values through a virtual stack.
Running a script from C
// host.c — compile with: cc host.c -llua -lm -o host
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>
// A C function callable from Lua: add(a, b)
static int l_add(lua_State *L) {
lua_Number a = luaL_checknumber(L, 1); // argument 1
lua_Number b = luaL_checknumber(L, 2); // argument 2
lua_pushnumber(L, a + b); // push the result
return 1; // number of results
}
int main(void) {
lua_State *L = luaL_newstate(); // create a Lua state
luaL_openlibs(L); // load the standard libraries
lua_register(L, "add", l_add); // expose add() to scripts
if (luaL_dofile(L, "script.lua") != LUA_OK) {
fprintf(stderr, "error: %s\n", lua_tostring(L, -1));
return 1;
}
// Call the Lua function greet("Ada") defined in script.lua
lua_getglobal(L, "greet");
lua_pushstring(L, "Ada");
if (lua_pcall(L, 1, 1, 0) == LUA_OK) {
printf("Lua returned: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
lua_close(L);
return 0;
}
-- illustrative
-- script.lua
print("2 + 3 =", add(2, 3))
function greet(name)
return "Hello, " .. name .. "!"
end
$ ./host
2 + 3 = 5.0
Lua returned: Hello, Ada!
The stack
Every value passed between C and Lua goes through the stack:
lua_push*functions push values (lua_pushnumber,lua_pushstring,lua_newtable).lua_to*andluaL_check*read them by index —1is the bottom (first argument),-1the top.- A C function receives its arguments on the stack and returns the number of results it pushed.
lua_pcallcalls a Lua function in protected mode — never let Lua errors unwind through C++ code without it.
Exposing objects: userdata
To give scripts a C object (a sprite, a file, a socket), create a
full userdata with lua_newuserdatauv, give it a metatable with
methods (luaL_newmetatable / luaL_setfuncs), and a __gc metamethod to
free it. Scripts then call sprite:move(10, 0) as if it were a Lua object.
Binding libraries
Writing bindings by hand is educational but tedious. sol2 (C++), mlua (Rust), NLua / MoonSharp (.NET), and gopher-lua (Go) generate bindings or implement Lua directly in those languages.