I'm using the Lua C API in C++ and I'm wrapping it into a class as follows:
class LuaScripting {
public:
lua_State *lua;
LuaScripting();
~LuaScripting();
bool execute_script(const std::string &script);
};
LuaScripting::LuaScripting() {
lua = luaL_newstate(); /* Opens Lua */
luaL_openlibs(lua); /* Opens the standard libraries */
/* Register our custom function(s) */
lua_register(lua, "write8", lua_write8);
lua_register(lua, "write16", lua_write16);
lua_register(lua, "write32", lua_write32);
lua_register(lua, "read8", lua_read8);
lua_register(lua, "read16", lua_read16);
lua_register(lua, "read32", lua_read32);
lua_register(lua, "math_sin", math_sin);
}
LuaScripting::~LuaScripting() {
lua_close(lua); /* Clean up lua */
}
I'm testing it as follows:
int main() {
// Disable buffering
setbuf(stdout, nullptr);
LuaScripting lua_scripting;
testWritingInt8(lua_scripting);
testWritingInt16(lua_scripting);
testWritingInt32(lua_scripting);
testReadingInt32(lua_scripting);
test_math_sin(lua_scripting);
return EXIT_SUCCESS;
}
The problems I'm having:
- After the first
testWritingInt8()the class destructor is called which will runlua_close(lua)even though the class instance didn't fall out of scope, yet. I'm not using any threads. Why is this happening? - When calling
lua_close(lua)the program crashes, why? - After commenting out
lua_close(lua)the write test cases run successfully but thereadXX()ormath_sin()return with an empty stack despite pushing a value onto the stack. Why?
Implementation:
static int math_sin(lua_State *lua) {
const auto value = luaL_checknumber(lua, 1);
const auto sine_result = sin(value);
lua_pushnumber(lua, sine_result);
return 1;
}
Test case:
void test_math_sin(LuaScripting &lua_scripting) {
std::stringstream lua_script_builder;
const auto target_value = 90.f;
lua_script_builder << "math_sin(" << target_value << ")";
const auto script_result = lua_scripting.execute_script(lua_script_builder.str());
assert(script_result == LUA_OK);
// TODO Not working
const auto read_value = (int32_t) lua_tonumber(*lua_scripting.lua, -1);
assert(target_value == read_value);
}
I'm always using the same lua_State * and I only call luaL_newstate() once.
As an attempted fix I tried to declare the lua state as a non-pointer:
lua_State lua; // error: aggregate ‘lua_State lua’ has incomplete type and cannot be defined
But doing this does not compile.
Adding another level of indirection via lua_State **lua fixes the crashing problem with lua_close() but does not fix any of the other issues.