如果应用调用了 Lua API
中的函数,就可能发生错误。正如前文所述, Lua
语言通常通过长跳转来提示错误。但是,如果没有相应的 setjmp
,解释器就无法进行长跳转。此时, API
中的任何错误都会导致 Lua
调用紧急函数( panic function
),当这个函数返回后,应用就会退出。我们可以通过函数 lua_atpanic
来设置自己的紧急函数,但作用不大。
要正确的处理应用代码中的错误,就必须通过 Lua
语言调用我们自己的代码,这样 Lua
语言才能设置合适的上下文来捕获异常,即在 setjmp
的上下文中运行代码。类似通过函数 pcall
在保护模式中运行 Lua
代码,我们也可以用函数 lua_pcall
运行 C
代码。更具体地说,可以把 C
代码封装到一个函数 F
中,然后使用 lua_pcall
调用这个函数F。通过这种方式,我们的 C
代码会在保护模式下运行。即便发生内存分配失败,函数 lua_pcall
也会返回一个对应的错误码,使解释器能保持一致的状态( consistent state
),如下所示:
static int foo (lua_State *L) { // code to run in protected code (要以保护模式运行的代码) return 0; } int secure_foo (lua_State *L) { lua_pushcfunction(L, foo); // 将'foo'作为乱函数压栈 return (lua_pcall(L, 0, 0, 0) == 0); }点击复制复制失败已复制
在上述示例中,无论发生什么,调用 secure_foo
时都会返回一个布尔值,来表示 foo
执行是否成功。特别的,请注意,栈中已经预先分配了空间,而且函数 lua_pushcfunction
不会分配内存,这样才不会引发错误。(函数 foo
的原型是函数 lua_pushcfunction
所要求的,后者用于在 Lua
中创建一个代表 C
函数的 Lua
函数。)