lua 源码系列文章:
lua源码欣赏的第五章的内容,是与 lua 闭包相关的内容
Contents
Lua 闭包概念
在 Lua 中,将一组数据绑定到特定函数上,即为闭包。被绑定的数据成为 upval,也可以成为非局部变量(区别于局部变量和全局变量)。
闭包的实现与分类
Lua 的函数区别于 C 中的函数,Lua 的函数可以在虚拟机运行时动态生成,可以在 Lua 的函数中生成函数。将 Lua 的函数原型与一组 upval 绑定,即 Proto
结构体与 UpVal
绑定在一起,就是 Lua 中闭包的实现方式。
Lua 中有两种闭包:Lua 闭包与 C 闭包。其中 Lua 闭包较为复杂。
- 虚拟机运行时生成闭包: 在函数退出之前,使用一个数据栈上的索引来映射局部变量,此时的 upval 称为开放的。当外层函数返回,使用数据栈空间收缩,通过调用
luaF_close
来关闭,并将之前的指针指向一个安全的地方来存放。 - 从外部加载源码(二进制或文本)来生成闭包: 不使用数据栈上的局部变量作为 upval,而是重新创建 upval。补充说明:Lua 在加载外部代码时,Lua 代码会被编译成为函数原型,而 lua 的外部调用是不返回函数原型的,而是把这个函数原型转化为闭包。
C 闭包相对与 Lua 闭包较为简单,由于C 闭包不会引用外部的 upval,upval都为关闭状态。将 upval 绑定在 Closure 结构体上即可。C 闭包还有一种无 upval 的特殊情况,这种情况称之为轻量函数(C light function)。轻量函数不需要使用 UpVal 结构体,也不需要 GC 来管理。
C 技巧
在 Lua 源码中,有用到 UNUSED()
宏,是为了避免编译器未使用的警告,源码如下:
|
|
https://github.com/xiaocang/lua-5.2.2_with_comments/releases/tag/lua_closure_06