我正在使用lua,我知道pcall用于受保护的调用,我的问题是,如果两种方式都调用同一个C代码。 e.g。
function a(arg)
...
end
正常通话:
a(arg)
受保护的电话:
pcall(a, arg)
实际上我正在使用'lua_lock / lua_unlock'来保护lua_State免受破坏。并形成源(lua 5.1.4)我可以看到'lua_pcall'正在调用'lua_lock / lua_unlock',但我不确定函数调用的正常方式是否也基于'lua_pcall'或使用'lua_lock / lua_unlock'?如果没有,这是否意味着我必须将所有调用'pcall(...)'的函数更改为从'lua_lock / lua_unlock'中获益?
有人可以解释一下吗?谢谢
答案 0 :(得分:17)
pcall
用于处理lua中的错误。我做了以下示例来演示如何使用它:
首先我们制作一个 知道 的函数会产生错误
function makeError(n)
return 'N'+n;
end
现在作为我们的第一个例子,我们定义了以下
function pcallExample1()
if pcall(makeError,n) then
print("no error!")
else
print("That method is broken, fix it!")
end
end
我们调用pcallExample1
pcallExample1()
获得输出:
Lua 5.1.3 Copyright (C) 1994-2008 Lua.org, PUC-Rio
That method is broken, fix it!
为了证明相反的结果:
function pcallExample2()
if makeError(5) then
print("no error!")
else
print("That method is broken, fix it!")
end
end
调用此方法会使错误保持不变,并冒泡到显示屏:
lua: /Users/henryhollinworth/Desktop/s.lua:2: attempt to perform arithmetic on a string value
就C
而言,pcall定义为
static int luaB_pcall (lua_State *L) {
int status;
luaL_checkany(L, 1);
lua_pushnil(L);
lua_insert(L, 1); /* create space for status result */
status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont);
return finishpcall(L, (status == LUA_OK));
}
lua_pcallk
LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc,
int ctx, lua_CFunction k) {
struct CallS c;
int status;
ptrdiff_t func;
lua_lock(L);
api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
if (errfunc == 0)
func = 0;
else {
StkId o = index2addr(L, errfunc);
api_checkvalidindex(L, o);
func = savestack(L, o);
}
c.func = L->top - (nargs+1); /* function to be called */
if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */
c.nresults = nresults; /* do a 'conventional' protected call */
status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);
}
else { /* prepare continuation (call is already protected by 'resume') */
CallInfo *ci = L->ci;
ci->u.c.k = k; /* save continuation */
ci->u.c.ctx = ctx; /* save context */
/* save information for error recovery */
ci->u.c.extra = savestack(L, c.func);
ci->u.c.old_allowhook = L->allowhook;
ci->u.c.old_errfunc = L->errfunc;
L->errfunc = func;
/* mark that function may do error recovery */
ci->callstatus |= CIST_YPCALL;
luaD_call(L, c.func, nresults, 1); /* do the call */
ci->callstatus &= ~CIST_YPCALL;
L->errfunc = ci->u.c.old_errfunc;
status = LUA_OK; /* if it is here, there were no errors */
}
adjustresults(L, nresults);
lua_unlock(L);
return status;
}
与lua_callk
LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx,
lua_CFunction k) {
StkId func;
lua_lock(L);
api_check(L, k == NULL || !isLua(L->ci),
"cannot use continuations inside hooks");
api_checknelems(L, nargs+1);
api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread");
checkresults(L, nargs, nresults);
func = L->top - (nargs+1);
if (k != NULL && L->nny == 0) { /* need to prepare continuation? */
L->ci->u.c.k = k; /* save continuation */
L->ci->u.c.ctx = ctx; /* save context */
luaD_call(L, func, nresults, 1); /* do the call */
}
else /* no continuation or no yieldable */
luaD_call(L, func, nresults, 0); /* just do the call */
adjustresults(L, nresults);
lua_unlock(L);
}
请注意,两者都使用lua_lock()
和lua_unlock()
。锁定和解锁lua_State
。