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);