lua源码分析之函数调用

lua源码分析之函数调用根据 lua5 1 4 版 的源码分析其函数调用的原理 函数调用分为受保护调用和不受保护的调用 lua 函数的调用原理主要分为 1 受保护调用 用 C 层面的堆栈来保护和恢复状态 2 不受保护的调用 使用自定义的栈存储结构 CallInfo 数组作为调用栈 修正数据栈 然后把字节码的执行位置跳转到被调用的函数开头 lua 函数的 return 操作则做了相反的操作

大家好,我是讯享网,很高兴认识大家。

根据lua5.1.4版 的源码分析其函数调用的原理。

lua函数的调用原理主要分为:

(1)受保护调用,用C层面的堆栈来保护和恢复状态

(2)不受保护的调用,使用自定义的栈存储结构CallInfo数组作为调用栈,修正数据栈,然后把字节码的执行位置跳转到被调用的函数开头,


讯享网

本文目录:

1、受保护的函数调用
2、不受保护的函数调用
(1)luaD_precall 环境保存
(2)luaD_poscall 环境恢复
3、函数调用使用实例
(1)不受保护的函数调用
(2)受保护的函数调用



本文内容:
1、受保护的函数调用
受保护的函数调用用C层面的堆栈来保护和恢复状态。
受保护的函数调用可以看成是一个 C 层面意义上完整的过程。在 lua 代码中,pcall是用函数而不是语
言机制完成的。受保护的函数调用一定在 C 层面进出了一次调用栈。它使用独立的一个内部 API luaD_pcall
来实现。公开API 仅需要对它做一些封装即可。
源代码lua5.14版 ldo.c :luaD_pcall(369行)
LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); api_checknelems(L, nargs+1);//检查栈上元素个数 checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { StkId o = index2adr(L, errfunc); api_checkvalidindex(L, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ c.nresults = nresults; status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); adjustresults(L, nresults); lua_unlock(L); return status; }

讯享网

讯享网int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef) { int status; unsigned short oldnCcalls = L->nCcalls; ptrdiff_t old_ci = saveci(L, L->ci); lu_byte old_allowhooks = L->allowhook; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = ef; status = luaD_rawrunprotected(L, func, u); if (status != 0) { /* an error occurred? */ StkId oldtop = restorestack(L, old_top); luaF_close(L, oldtop); /* close eventual pending closures */ luaD_seterrorobj(L, status, oldtop); L->nCcalls = oldnCcalls; L->ci = restoreci(L, old_ci); L->base = L->ci->base; L->savedpc = L->ci->savedpc; L->allowhook = old_allowhooks; restore_stack_limit(L); } L->errfunc = old_errfunc; return status; }


从这段代码我们可以看到pcall的处理模式:用C层面的堆栈来保护和恢复状态。


ci(调用栈)、allowhooks(钩子)、errfunc(函数错误时的栈索引)都保护在luaD_pcall的C堆栈上,一旦出错(luaD_rawrunprotected判断),就可以恢复lua的运行环境。

luaD_rawrunprotected没有正确返回是,需要根据old_top找到堆栈上的刚才调用的函数,给它做弹栈操作。因为luaD_rawrunprotected调用的是一个函数对象,
小讯
上一篇 2025-02-23 19:14
下一篇 2025-03-25 11:50

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/71541.html