将 Lua 包装成 C++ class 的问题
Problems with wrapping Lua into a C++ class
我在 C++
中使用 Lua C API
并将其包装到 class 中,如下所示:
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 实例没有超出范围, 然而。我没有使用任何线程。为什么会这样?
- 调用
lua_close(lua)
时程序崩溃,为什么?
- 注释掉
lua_close(lua)
后,编写测试用例 运行 成功,但 readXX()
或 math_sin()
return 尽管将值压入,但堆栈为空堆栈。为什么?
实施:
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 状态声明为非指针:
lua_State lua; // error: aggregate ‘lua_State lua’ has incomplete type and cannot be defined
但是这样做不会编译。
通过 lua_State **lua
添加另一个间接级别修复了 lua_close()
的崩溃问题,但没有解决任何其他问题。
那是因为您正在复制 LuaScripting
对象。我敢打赌 testWritingInt8
是这样声明的:
void testWritingInt8(LuaScripting lua)
注意 lua
参数不是指针或对 LuaScripting 对象的引用,它 是 一个 LuaScripting 对象.
因此,当您调用 testWritingInt8(lua)
时,计算机将 LuaScripting 对象复制到一个新对象中,调用函数,并在调用结束时销毁新对象。
现在,为什么会崩溃?嗯,你的 LuaScripting
class 没有复制构造函数(LuaScripting(const LuaScripting &)
)所以编译器创建一个默认的,它只复制所有成员变量 - 在这种情况下 lua
指针被复制。然后,当新对象被销毁时,它会释放 Lua 状态。
解决方案:通过删除复制构造函数,使 LuaScripting
对象不会被意外复制。也是赋值运算符。
// inside LuaScripting
LuaScripting(const LuaScripting &) = delete;
LuaScripting &operator =(const LuaScripting &) = delete;
然后确保通过引用传递 LuaScripting
值。
如果您希望能够 移动 LuaScripting
对象 - 例如,如果您希望将它们存储在一个向量中,但仍然不复制它们 - 您可以定义 移动构造函数 和 移动赋值运算符 ,这超出了本答案的范围。
您的 math_sin
测试用例没有 return 堆栈上的任何值,因为...您的脚本没有 return 任何值。尝试 return math_sin(target_value)
而不是 math_sin(target_value)
.
我在 C++
中使用 Lua C API
并将其包装到 class 中,如下所示:
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 实例没有超出范围, 然而。我没有使用任何线程。为什么会这样? - 调用
lua_close(lua)
时程序崩溃,为什么? - 注释掉
lua_close(lua)
后,编写测试用例 运行 成功,但readXX()
或math_sin()
return 尽管将值压入,但堆栈为空堆栈。为什么?
实施:
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 状态声明为非指针:
lua_State lua; // error: aggregate ‘lua_State lua’ has incomplete type and cannot be defined
但是这样做不会编译。
通过 lua_State **lua
添加另一个间接级别修复了 lua_close()
的崩溃问题,但没有解决任何其他问题。
那是因为您正在复制 LuaScripting
对象。我敢打赌 testWritingInt8
是这样声明的:
void testWritingInt8(LuaScripting lua)
注意 lua
参数不是指针或对 LuaScripting 对象的引用,它 是 一个 LuaScripting 对象.
因此,当您调用 testWritingInt8(lua)
时,计算机将 LuaScripting 对象复制到一个新对象中,调用函数,并在调用结束时销毁新对象。
现在,为什么会崩溃?嗯,你的 LuaScripting
class 没有复制构造函数(LuaScripting(const LuaScripting &)
)所以编译器创建一个默认的,它只复制所有成员变量 - 在这种情况下 lua
指针被复制。然后,当新对象被销毁时,它会释放 Lua 状态。
解决方案:通过删除复制构造函数,使 LuaScripting
对象不会被意外复制。也是赋值运算符。
// inside LuaScripting
LuaScripting(const LuaScripting &) = delete;
LuaScripting &operator =(const LuaScripting &) = delete;
然后确保通过引用传递 LuaScripting
值。
如果您希望能够 移动 LuaScripting
对象 - 例如,如果您希望将它们存储在一个向量中,但仍然不复制它们 - 您可以定义 移动构造函数 和 移动赋值运算符 ,这超出了本答案的范围。
您的 math_sin
测试用例没有 return 堆栈上的任何值,因为...您的脚本没有 return 任何值。尝试 return math_sin(target_value)
而不是 math_sin(target_value)
.