[英]Problems with wrapping Lua into a C++ class
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 */
}
我正在测试它如下:
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;
}
我遇到的问题:
testWritingInt8()
之后,调用 class 析构函数,它将运行lua_close(lua)
,即使 class 实例还没有脱离 Z31A1FD140BE4BEF2D11E121EC9A18A58。 我没有使用任何线程。 为什么会这样?lua_close(lua)
时程序崩溃,为什么?lua_close(lua)
后,写入测试用例成功运行,但readXX()
或math_sin()
返回一个空堆栈,尽管将一个值推入堆栈。 为什么?执行:
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;
}
测试用例:
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);
}
我总是使用相同的lua_State *
并且我只调用luaL_newstate()
一次。
作为尝试的修复,我尝试将 lua state 声明为非指针:
lua_State lua; // error: aggregate ‘lua_State lua’ has incomplete type and cannot be defined
但是这样做不会编译。
通过lua_State **lua
添加另一个间接级别修复了lua_close()
的崩溃问题,但没有修复任何其他问题。
那是因为您正在复制LuaScripting
object。 我敢打赌testWritingInt8
是这样声明的:
void testWritingInt8(LuaScripting lua)
请注意lua
参数不是指针或对 LuaScripting object 的引用,它是LuaScripting object。
因此,当您调用testWritingInt8(lua)
时,计算机会将 LuaScripting object 复制到一个新的,调用 function,并在调用结束时销毁新的。
现在,为什么会崩溃? 好吧,您的LuaScripting
class 没有复制构造函数( LuaScripting(const LuaScripting &)
),因此编译器创建了一个默认构造函数,它只复制所有成员变量 - 在这种情况下,复制了lua
指针。 然后,当新的 object 被销毁时,它会释放 Lua state。
解决方案:通过删除复制构造函数,使LuaScripting
对象不会被意外复制。 还有赋值运算符。
// inside LuaScripting
LuaScripting(const LuaScripting &) = delete;
LuaScripting &operator =(const LuaScripting &) = delete;
然后确保通过引用传递LuaScripting
值。
如果您希望能够移动LuaScripting
对象 - 例如,如果要将它们存储在向量中,但仍不复制它们 - 您可以定义移动构造函数和移动赋值运算符,它们不在此答案的 scope 范围内。
您的math_sin
测试用例不会在堆栈上返回任何值,因为......您的脚本不会返回任何值。 尝试return math_sin(target_value)
而不仅仅是math_sin(target_value)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.