Embedding Lua in C/C++
32.1 A Minimal Host Program
// host.c → gcc host.c -o host -llua -lm -ldl (adjust: -llua5.4 and -I/usr/include/lua5.4 on Debian)
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
int main(void) {
lua_State *L = luaL_newstate(); // create a new Lua state
luaL_openlibs(L); // open the standard libraries
if (luaL_dostring(L, "print('Hello from embedded Lua!')") != LUA_OK) {
fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
}
if (luaL_dofile(L, "config.lua") != LUA_OK) { // config.lua: width = 800; title = "Game"
fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1);
} else {
lua_getglobal(L, "width");
lua_getglobal(L, "title");
long long width = luaL_checkinteger(L, -2);
const char *title = luaL_checkstring(L, -1);
printf("Window: %s (%lld)\n", title, width);
lua_pop(L, 2);
}
// Call a Lua function: function add(a, b) return a + b end
luaL_dostring(L, "function add(a, b) return a + b end");
lua_getglobal(L, "add");
lua_pushinteger(L, 2);
lua_pushinteger(L, 3);
if (lua_pcall(L, 2, 1, 0) =
…32.2 The Virtual Stack
C and Lua exchange values through a stack. Positive indices count from the bottom (1 = first), negative indices from the top (-1 = top).
lua_pushnil, lua_pushboolean, lua_pushinteger, lua_pushnumber, lua_pushstring, lua_pushlstring, lua_pushfstring, lua_pushcfunction, lua_pushvalue
lua_type, lua_isinteger, lua_isnumber, lua_isstring, lua_istable, lua_isfunction, lua_isnoneornil
lua_toboolean, lua_tointeger, lua_tonumber, lua_tolstring, lua_touserdata
luaL_checkinteger, luaL_checknumber, luaL_checkstring, luaL_optinteger, luaL_checktype, luaL_argerror
lua_gettop, lua_settop, lua_pop, lua_insert, lua_remove, lua_replace, lua_rotate, lua_copy, lua_checkstack
lua_newtable, lua_createtable, lua_getfield, lua_setfield, lua_gettable, lua_settable, lua_geti, lua_seti, lua_rawget, lua_rawset, lua_next lua_getglobal, lua_setglobal
lua_call, lua_pcall, lua_callk/lua_pcallk (continuations) lua_error, luaL_error
32.3 Reading a Lua Table from C
Careful: lua_tostring on a numeric key converts it in place and confuses lua_next. Use luaL_tolstring (which pushes a copy), or check lua_type first.
// config.lua: window = { width = 1024, height = 768, fullscreen = false }
lua_getglobal(L, "window");
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "width"); int w = (int)luaL_checkinteger(L, -1); lua_pop(L, 1);
lua_getfield(L, -1, "fullscreen"); int fs = lua_toboolean(L, -1); lua_pop(L, 1);
printf("%d %d\n", w, fs);
}
lua_pop(L, 1);
// Iterate any table
lua_getglobal(L, "window");
lua_pushnil(L); // first key
while (lua_next(L, -2) != 0) { // pushes key, value
const char *k = luaL_tolstring(L, -2, NULL); // pushes a string COPY of the key
const char *v = luaL_tolstring(L, -2, NULL); // the value is now at -2
printf("%s = %s\n", k, v);
lua_pop(L, 3); // pop both strings and the value; keep the key for lua_next
}
lua_pop(L, 1);