10

I am using lua and I know pcall is for protected calling and my question is if both ways of calling all come down to the same C code. e.g.

function a(arg)
   ...
end

normal calling:

a(arg)

protected call:

pcall(a, arg)

Actually I am using 'lua_lock/lua_unlock' to protect the lua_State from corrupting. And form the source (lua 5.1.4) I can see 'lua_pcall' is calling 'lua_lock/lua_unlock', but I am not sure if normal way of function call is also based on 'lua_pcall' or using 'lua_lock/lua_unlock'? If not, does it mean that I have to change all the function calling to 'pcall(...)' to get benefit from 'lua_lock/lua_unlock'?

Could someone explain? Thank you

4

1 回答 1

18

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.

于 2013-05-20T04:27:23.097 回答