LUA_API intlua_pcallk(lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k){ structCallSc; int status; ptrdiff_t func; lua_lock(L); api_check(k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); api_checknelems(L, nargs+1); api_check(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_checkstackindex(errfunc, 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->extra = savestack(L, c.func); ci->u.c.old_errfunc = L->errfunc; L->errfunc = func; setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ 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; }
可以看到,首先获取需要调用的函数指针:
1
c.func = L->top - (nargs+1); /* function to be called */
/* ** Function Prototypes */ typedefstructProto { CommonHeader; lu_byte numparams; /* number of fixed parameters */ lu_byte is_vararg; lu_byte maxstacksize; /* maximum stack used by this function */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ int sizecode; int sizelineinfo; int sizep; /* size of 'p' */ int sizelocvars; int linedefined; int lastlinedefined; TValue *k; /* constants used by the function */ Instruction *code; structProto **p;/* functions defined inside the function */ int *lineinfo; /* map from opcodes to source lines (debug information) */ LocVar *locvars; /* information about local variables (debug information) */ Upvaldesc *upvalues; /* upvalue information */ structLClosure *cache;/* last created closure with this prototype */ TString *source; /* used for debug information */ GCObject *gclist; } Proto;