作為一個寄宿型的嵌入式語言,Lua設計更傾向由宿主語言(通常是C)處理錯誤。
但是可以在保護模式下,執行函式,並檢查函式是否執行成功。
很像是Go語言。這就是Lua的錯誤處理基本方法。
作為一個寄宿型的嵌入式語言,Lua設計更傾向由宿主語言(通常是C)處理錯誤。
num = 10
str = "string"
print('Hello, Lua')
result = num / str -- Error: attempt to div a 'number' with a 'string'
print('here will not show, because error hapend before')
一般來說,並不傾向於Lua處理最後,因為數字與字串相除,所引發的錯誤。這個錯誤會持續引發至宿主語言,由宿主語言進行錯誤處裡。
#include "lua.h"
#include "lauxlib.h"
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[]){
// new a lua VM
lua_State *L = luaL_newstate();
// open base lib
luaopen_base(L);
// dostring
/* 執行Lua片段 */
int lua_result = luaL_dostring(L,
"num = 10\n"
"str = 'string'\n"
"print('Hello, Lua')\n"
"result = num / str -- Error: attempt to div a 'number' with a 'string'\n"
"print('here will not show, because error hapend before')\n"
);
/* 檢查是否執行成功 */
if(lua_result == LUA_OK){
printf("run lua success.\n");
}else{
/* 處理錯誤 */
printf("error code: %d\n", lua_result);
/* 檢查錯誤訊息 */
if(lua_isstring(L, -1)){
const char *msg = lua_tostring(L, -1);
lua_pop(L, 1);
/* 顯示錯誤訊訊息 */
printf("Error Message: %s\n", msg);
}
}
return 0;
}
Hello, Lua
error code: 1
Error Message: [string "num = 10..."]:4: attempt to perform arithmetic on a string value (global 'str')
恩...你可能看不太懂,但大致可以看到與上方相同的Lua程式片段,並大概能夠理解由宿主語言去處理錯誤即可。與C交互並不是今天的重點。
與函數形語言裡的
call
不太一樣的,Lua的pcall
和xpcall
另有用途。
pcall
和xpcall
可以將特定函式於保護模式(protect mode)下執行。其p
即是protect(保護)的意思。
下面程式直接於Lua執行,並不會顯示錯誤訊息。
function error_chunk()
local num = 10
local str = "string"
print('Hello, Lua')
local result = num / str -- Error: attempt to div a 'number' with a 'string'
print('here will not show, because error hapend before')
end
pcall(error_chunk)
ok = pcall(error_chunk)
print(ok) -- Output: false
除了第一個反還值是執行是否成功以外,其他反還值才是函數真正執行結果:
function div(a,b)
return a/b
end
ok, c = pcall(div, 10, 2)
if ok then
print(c) --> Output: 5.0
end
執行失敗是不會有返回值的,以下面例子得到的是錯誤訊息。
ok, c = pcall(div, 10, "str")
if not ok then
print("Error Message: ")
print(c)
end
xpcall()
而外接受一個錯誤處理者。以下例來說,錯誤處理者會反還一個預設結果0.5
function errorHandle(msg)
print("Error Message"..msg)
return .5
end
ok, c = xpcall(div, errorHandle, 10, "str")
print("----------")
print(ok, c) -- false 0.5
Lua有兩種錯誤類型error
和warn
。
實際上warn()
並不算是錯誤,他不會中止程式執行,只會顯示一些訊息。
warn("Message") -- Output: Lua warning: Message
上面你可能沒看到顯示的錯誤訊息,這是因為一開始警告顯示是關閉的。你可以透過warn("@on")
開啟警告。
warn("@on")
可以透過warn("@off")
關閉警告。
warn("@off")
warn "message" -- no output
@
開頭是warn
的控制符,他會忽略非法的控制,像是下面即使開始警告,也不會有訊息:
warn("@on")
warn "@message" -- no output
error()
永遠不會返回。其函數原形為:
error (message [, level])
level
基本上可以不用理會,而message
通常是字串:
ok, msg = pcall(error, "Message")
print(ok, msg) -- false Message
不過也可以是其他類型:
ok, msg_obj = pcall(error, {message = "Message"})
print(ok, type(msg_obj)) -- false table
print(msg_obj.message) -- Message
這也是為什麼在C處理錯誤時,先檢查是否為字串。