从Lua调用函数时如何处理C++异常?

Jur*_*aho 22 c++ lua exception

我有一个工作的C++函数,我可以从Lua调用.为了证明我的问题,这里有一个例子:

int PushHello(lua_State *L){
    string str("Hello");
    lua_pushlstring(L, str.data(), str.length());
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

注意:我知道我不必在那里使用字符串变量,但它是为了证明这个问题.

这是我的两个问题:

  1. 当我从Lua字符串构造函数调用此函数时可能会抛出异常.那是问题吗?Lua会处理它并正确解开Lua堆栈吗?我不这么认为.我怎么解决这个问题?我是否需要添加try/catch所有此类代码并将异常转换为lua_error?是不是有更好的解决方案?

  2. 我可能通过将Lua编译为C++来解决的另一个问题是,如果使用longjmp,则lua_pushlstring()调用lua_error()字符串析构函数时不会调用它.通过编译为C++并抛出异常而不是使用longjmp来解决问题吗?

为了澄清,我可以看到问题1的可能解决方案是:

int PushHello(lua_State *L){
    string str;
    try{
        str.assign("Hello");
    catch(exception &e){
        luaL_error(L, e.what());
    }
    lua_pushlstring(L, str.data(), str.length());
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

但这非常难看并且容易出错,因为try/catch需要添加到许多地方.它可以作为一个宏来完成并放置每个可以抛出的命令,但这不会更好.

Jur*_*aho 8

我找到了合理的解决方案.问题是它是否正确.不是导出(或通过lua_cpcall调用)原始函数,而是导出/调用int PushHello(lua_State *L)包装器int SafeFunction<PushHello>(lua_State *L).包装器看起来像:

template<lua_CFunction func>
int SafeFunction(lua_State *L){
    int result = 0;
    try{
        result = func(L);
    }
    // transform exception with description into lua_error
    catch(exception &e){
        luaL_error(L, e.what());
    }
    // rethrow lua error - C++ Lua throws lua_longjmp*
    catch(lua_longjmp*){
        throw;
    }
    // any other exception as lua_error with no description
    catch(...){
        luaL_error(L, "Unknown error");
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

你怎么看待这件事?你看到有什么问题吗?