Lua的基本信息调试

来源:互联网 发布:npm 换淘宝源 编辑:程序博客网 时间:2024/05/17 09:26

前段时间在项目中试加入了lua脚本,但由于匆忙很不完善,没有任何的调试信息,包括出错信息的打印,所以很是痛苦!最近终于开始着手完善lua程序,只是从没用过,一切都是从头学起!

首先是载入脚本的时候:luaL_dofile(m_lua, pathname.c_str());

如果是lua脚本的语法等基本错误,这时候luaL_ dofile会返回错误码,但想知道错误信息就必须看堆栈了。

其实查看文档就知道,luaL_dofile分两步:luaL_loadfile以及lua_pcall,因此可以加入如下信息:

    if (luaL_loadfile(m_lua, pathname.c_str()) != 0) {
          std::cout<<"loadfile error[file:"<<pathname.c_str()<<"]: "<<lua_tostring(m_lua, -1)<<endl;
    }
     if (lua_pcall(m_lua, 0, LUA_MULTRET, 0) != 0) {
          std::cout<<"pcall error[file:"<<pathname.c_str()<<"]: "<<lua_tostring(m_lua, -1)<<endl;
     }

这样就是在load的时候把基本的语法错误信息给打印出来。

 

第二,在lua运行中出错,这个就比较麻烦点了,在我们的项目中使用的是luabind。

调用lua函数的接口是:call_function<bool>(m_lua, func_name, player);

如果func出错了,lua会抛出异常,c++程序捕捉到后程序可能会崩掉(就看有没有对异常的抛出做反映),所以光写call_function这个函数的话是看不到错误信息的,我们需要把异常捕捉出来。

    try {
            bool ret = call_function<bool>(m_lua, func_name, player);
            return ret;
    } catch(luabind::error& e) {
            ERROR_LOG("AI[%u] throw error: err_msg[%s]", player->id, lua_tostring(m_lua, -1));
            return false;
    }

这样我们就能从堆栈中获取抛出的异常,同时程序也不会因此而崩掉!

当然,这些只能打印简单的错误信息,详细的需要用lua_Debug,这个后续给出。。。


前面说过,在我们的项目中使用的是luabind。

调用lua函数的接口是:call_function<bool>(m_lua, func_name, player);

如果func出错了,lua会抛出异常,c++程序捕捉到后程序可能会崩掉(就看有没有对异常的抛出做反映),所以光写call_function这个函数的话是看不到错误信息的,我们需要把异常捕捉出来。

    try {
            bool ret = call_function<bool>(m_lua, func_name, player);
            return ret;
    } catch(luabind::error& e) {
            ERROR_LOG("AI[%u] throw error: err_msg[%s]", player->id, lua_tostring(m_lua, -1));
            return false;
    }

这样我们就能从堆栈中获取抛出的异常,同时程序也不会因此而崩掉!

 

但是这样显示的异常可能还不够完整,我们又是想知道出错在哪个lua脚本的哪行代码上,这就需要使用lua_Debug来调用信息。

通过查阅luabind和lua的参考手册(以后要养成这样的习惯,不能全依赖于google)发现,在call_function的调用抛出异常以后,这个function已经从stack中删除,所以使用lua_getstack会失败。luabind手册中点明可以通过luabind::set_pcall_callback这个函数来自定义lua_pcall的错误处理函数。

因此:

自定义错误处理函数:

int pcall_callback_err_fun(lua_State* L)
{
    lua_Debug debug;
    lua_getstack(L, 2, &debug);
    lua_getinfo(L, "Sln", &debug);

    std::string err = lua_tostring(L, -1);
    lua_pop(L, 1);
    std::stringstream msg;
    msg << debug.short_src << ":line " << debug.currentline;
    if (debug.name != 0) {
        msg << "(" << debug.namewhat << " " << debug.name << ")";
    }

    msg << " [" << err << "]";
    lua_pushstring(L, msg.str().c_str());
    return 1;
}

绑定函数:

luabind::set_pcall_callback(pcall_callback_err_fun);

注意的是:lua_getstack(L, 2, &debug)中参数level需要设置为2,关于这个还在研究中。。。



在前面那篇文章Lua的基本信息调试(二)中,我使用了lua_getstack(L, 2, &debug);去取堆栈中的错误信息,但至于错误信息在stack中的层数并不清楚,经过信息打印发现,错误信息在stack的最深处,因此,修改函数为:

int pcall_callback_err_fun(lua_State* L)
{
    lua_Debug debug;

   

    //取得层数

    uint32_t level = 0;
    while (lua_getstack(L, level, &debug)) {
        level++;
    }

    if (!level) {
        return 0;
    }


    lua_getstack(L, level, &debug);
    lua_getinfo(L, "Sln", &debug);

    std::string err = lua_tostring(L, -1);
    lua_pop(L, 1);
    std::stringstream msg;
    msg << debug.short_src << ":line " << debug.currentline;
    if (debug.name != 0) {
        msg << "(" << debug.namewhat << " " << debug.name << ")";
    }

    msg << " [" << err << "]";
    lua_pushstring(L, msg.str().c_str());
    return 1;
}

这样我们就能准确的获得lua脚本在运行中的错误信息!


0 0
原创粉丝点击