繁体   English   中英

将 Lua 包装到 C++ class 的问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM