2013-05-20 4 views
8

Ich bin mit lua und ich weiß, pcall für geschützte Berufung und meine Frage ist, ob beide Wege, alle kommen auf das gleiche C-Code aufrufen. z.B.Was ist der Unterschied hinter normalen Funktionsaufruf und pcall

function a(arg) 
    ... 
end 

normaler calling:

a(arg) 

geschützt Aufruf:

pcall(a, arg) 

Eigentlich verwende ich 'lua_lock/lua_unlock' die lua_State von verderblichen zu schützen. Und bilden die Quelle (lua 5.1.4) ich sehe ‚lua_pcall‘ ruft ‚lua_lock/lua_unlock‘, aber ich bin nicht sicher, ob normale Art und Weise der Funktionsaufruf auch auf ‚lua_pcall‘ basiert oder mit ‚lua_lock/lua_unlock‘? Wenn nicht, bedeutet das, dass ich alle Funktionen, die zu 'pcall (...) aufrufen, ändern muss, um von' lua_lock/lua_unlock 'profitieren zu können?

Könnte jemand erklären? Danke

Antwort

15

pcall wird verwendet, um Fehler in lua zu behandeln. Ich habe das folgende Beispiel gemacht zu zeigen, wie es zu benutzen:

Zuerst haben wir eine Funktion machen, die mich wissen einen Fehler produzieren

function makeError(n) 
    return 'N'+n; 
end 

nun als unser erstes Beispiel definieren wir die folgende

function pcallExample1() 
    if pcall(makeError,n) then 
     print("no error!") 
    else 
     print("That method is broken, fix it!") 
    end 
end 

Wir rufen pcallExample1

pcallExample1() 

Und die Ausgabe erhalten:

Lua 5.1.3 Copyright (C) 1994-2008 Lua.org, PUC-Rio 
That method is broken, fix it! 

, das Gegenteil zu beweisen:

function pcallExample2() 
    if makeError(5) then 
     print("no error!") 
    else 
     print("That method is broken, fix it!") 
    end 
end 

dies den Fehler haben Aufrufen bleiben unhanded und Blase bis zur Anzeige:

lua: /Users/henryhollinworth/Desktop/s.lua:2: attempt to perform arithmetic on a string value 

In Bezug auf C wird pcall als

definiert
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)); 
} 

Wo lua_pcallk

ist
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; 
} 

Im Gegensatz zu 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); 
} 

Beachten Sie, dass sowohl die Verwendung von lua_lock() und lua_unlock() machen. Sperren und entsperren Sie die lua_State.

+0

Beachten Sie, dass in der Regel - vor allem für die Entwicklung - mit 'xpcall' vorzuziehen, da Sie tatsächlich eine Fehlermeldung und Rückverfolgungs aus ihm heraus bekommen, während es immer noch nicht die Lua-Laufzeit im Falle eines Fehlers nicht beeinträchtigt. – dualed

Verwandte Themen