如何使用 Lua 的 C API 在控制台中打印错误

Rig*_*ggs 4 c c++ error-handling lua lua-c++-connection

我一直在寻找一种方法来处理 Lua 的 C API 错误,并在控制台中简单地将它们打印出来。虽然,我无法找到一个单一的工作示例。我想做的就是:

static int test(lua_State *L)
{
  if(!lua_isstring(L, 1))
     return luaL_error(L, "This is not a valid string");    
}
Run Code Online (Sandbox Code Playgroud)

或者

static int test(lua_State *L)
{
    try
    {
        if (!lua_isstring(L, 1))
        {
            throw luaL_error(L, "This is not a valid string");
        }
    }
    catch (int e)
    {
        std::cout << "Error " << e << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

但到目前为止,还没有任何效果。使用 LUA C API 进行错误处理并在控制台中显示消息的正确方法是什么?

cat*_*ell 5

第一个代码示例是处理 Lua 中错误的正确方法之一,但您似乎对其工作方式感到困惑。

您正在编写一个 C 函数,该函数实现了一个将暴露给 Lua 的接口。它的工作原理是这样的 Lua 代码:

local function test(s)
    if type(s) ~= "string" then
        error("This is not a valid string")
    end
end
Run Code Online (Sandbox Code Playgroud)

首先导致错误的代码不是test函数,而是使用无效参数调用它的代码。

当您的 Lua 代码以无效方式调用该函数时(例如test(42)),它将引发 Lua 错误,并将字符串作为错误消息。如果您从标准 Lua 解释器调用它,它将停止程序,打印错误消息和堆栈跟踪。

如果你想在你的 Lua 代码中做其他事情,例如只打印错误消息,你可以捕捉错误,pcall它的工作方式有点像其他语言中的 try / catch:

local ok, err_msg = pcall(test, 42)
if not ok then
    print(err_msg)
end
Run Code Online (Sandbox Code Playgroud)

请注意,由于此错误是由无效参数类型引起的,因此您的代码可能可以通过使用luaL_checkstring / luaL_checklstringluaL_argcheckluaL_argerror 之一而不是直接使用luaL_error来改进。

要了解有关 C API 如何工作的更多信息,我建议您阅读“Lua 编程(第 4 版)”一书中的专用部分。


And*_*urg 5

I had the exact same question, and catwell's answer didn't fully answer it for me. What I originally did in my program was simply call

luaL_dofile(L, "example.lua");
Run Code Online (Sandbox Code Playgroud)

Nothing happened when an error occurred.

"If you call it from a standard Lua interpreter..." was a good clue. So I looked at the main in luac.c to see what it does:

if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
Run Code Online (Sandbox Code Playgroud)

Note that luaL_dofile also expands to lua_pcall. So, if an error is raised while that file is ... done, the only thing that happens is that the error message is pushed onto L's stack. It is your responsibility to do something with it.

So I modified my code accordingly:

#include <stdio.h> // fprintf, stderr
#include <stdlib.h> // exit, EXIT_FAILURE
static void fatal(const char* message) {
  fprintf(stderr,"%s\n", message);
  exit(EXIT_FAILURE);
}
int main(void) {
  ...
  if (luaL_dofile(L, "example.lua") != LUA_OK) {
    fatal(lua_tostring(L,-1));
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)