[英]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: 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:我遇到的问题:
testWritingInt8()
the class destructor is called which will run lua_close(lua)
even though the class instance didn't fall out of scope, yet.在第一个testWritingInt8()
之后,调用 class 析构函数,它将运行lua_close(lua)
,即使 class 实例还没有脱离 Z31A1FD140BE4BEF2D11E121EC9A18A58。 I'm not using any threads.我没有使用任何线程。 Why is this happening?为什么会这样?lua_close(lua)
the program crashes, why?调用lua_close(lua)
时程序崩溃,为什么?lua_close(lua)
the write test cases run successfully but the readXX()
or math_sin()
return with an empty stack despite pushing a value onto the stack.注释掉lua_close(lua)
后,写入测试用例成功运行,但readXX()
或math_sin()
返回一个空堆栈,尽管将一个值推入堆栈。 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.我总是使用相同的lua_State *
并且我只调用luaL_newstate()
一次。
As an attempted fix I tried to declare the lua state as a non-pointer:作为尝试的修复,我尝试将 lua state 声明为非指针:
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.通过lua_State **lua
添加另一个间接级别修复了lua_close()
的崩溃问题,但没有修复任何其他问题。
That's because you are copying the LuaScripting
object.那是因为您正在复制LuaScripting
object。 I bet testWritingInt8
is declared like this:我敢打赌testWritingInt8
是这样声明的:
void testWritingInt8(LuaScripting lua)
Notice the lua
parameter is not a pointer or a reference to a LuaScripting object, it is a LuaScripting object.请注意lua
参数不是指针或对 LuaScripting object 的引用,它是LuaScripting object。
So when you call testWritingInt8(lua)
, the computer copies the LuaScripting object into a new one, calls the function, and destroys the new one at the end the call.因此,当您调用testWritingInt8(lua)
时,计算机会将 LuaScripting object 复制到一个新的,调用 function,并在调用结束时销毁新的。
Now, why does that crash?现在,为什么会崩溃? Well, your LuaScripting
class doesn't have a copy constructor ( LuaScripting(const LuaScripting &)
) so the compiler creates a default one, which just copies all the member variables - in this case the lua
pointer is copied.好吧,您的LuaScripting
class 没有复制构造函数( LuaScripting(const LuaScripting &)
),因此编译器创建了一个默认构造函数,它只复制所有成员变量 - 在这种情况下,复制了lua
指针。 Then, when the new object is destroyed, it frees the Lua state.然后,当新的 object 被销毁时,它会释放 Lua state。
Solution: Make it so LuaScripting
objects can't be copied accidentally, by deleting the copy constructor.解决方案:通过删除复制构造函数,使LuaScripting
对象不会被意外复制。 Also the assignment operator.还有赋值运算符。
// inside LuaScripting
LuaScripting(const LuaScripting &) = delete;
LuaScripting &operator =(const LuaScripting &) = delete;
Then make sure to pass LuaScripting
values by reference.然后确保通过引用传递LuaScripting
值。
If you want to be able to move LuaScripting
objects around - say, if you want to store them in a vector, but still not copy them - you can define a move constructor and move assignment operator , which are out of scope of this answer.如果您希望能够移动LuaScripting
对象 - 例如,如果要将它们存储在向量中,但仍不复制它们 - 您可以定义移动构造函数和移动赋值运算符,它们不在此答案的 scope 范围内。
Your math_sin
test case doesn't return any values on the stack because... your script doesn't return any values.您的math_sin
测试用例不会在堆栈上返回任何值,因为......您的脚本不会返回任何值。 Try return math_sin(target_value)
instead of just math_sin(target_value)
.尝试return math_sin(target_value)
而不仅仅是math_sin(target_value)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.