关于lua的闭包Closure和Upvalue

关于lua的闭包(Closure)和Upvalue

upvalue:嵌套函数的外部函数的局部变量
function func(a) <== 这个函数返回值是一个函数
return function ()
    a = a + 1    <== 这里可以访问外部函数func的局部变量a,这个变量a就是upvalue
    return a 
end
end

func返回一个匿名函数,可用变量接取之。该匿名函数一个upvalue a(有点像C函数的static变量),初值为首次调用func时的参数

闭包一个匿名函数加上其可访问的upvalue
c = func(1) <== c现在指向一个拥有upvalue a = 1的匿名函数,c也被称作一个闭包
c()          <== 返回2
c()          <== 返回3
c2 = func(1) <== c2现在指向另外一个拥有upvalue a = 1的匿名函数,c2也被称作一个闭包
c2()         <== 返回2

下面是示例代码

int 
generatecclosure(lua_State *L)        /* 闭包产生器 */
{
    lua_pushnumber(L,0);             /* 压入第一个upvalue */ 
    lua_pushnumber(L,0);             /* 压入第二个upvalue */
    lua_pushcclosure(L,cclosure,2); /* 压入闭包的同时也把upvalue置入该闭包的upvalue表 */
    return 1;                         /* 返回闭包 */
}

int 
cclosure(lua_State *L)
{
    double upval1,upval2;
    upval1 = lua_tonumber(L,lua_upvalueindex(1)); /* 注意upvalue索引1,2是闭包依赖的,不会和其他的闭包中的索引冲突 */
    upval2 = lua_tonumber(L,lua_upvalueindex(2));
    upval1++; upval2++;    
    lua_pushnumber(L,upval1); lua_replace(L,lua_upvalueindex(1));/* 更新upvalue1 */
    lua_pushnumber(L,upval2); lua_replace(L,lua_upvalueindex(2));/* 更新upvalue2 */
    lua_pushnumber(L,upval1 + upval2);
    return 1;
}

int 
generatecclosure2(lua_State *L)        
{
    lua_pushnumber(L,10);             
    lua_pushnumber(L,10);             
    lua_pushcclosure(L,cclosure2,2); 
    return 1;                          
}

int 
cclosure2(lua_State *L)
{
    double upval1,lua_upvalueindex(1));
    upval2 = lua_tonumber(L,lua_upvalueindex(2));
    upval1++; upval2++;
    lua_pushnumber(L,lua_upvalueindex(1));
    lua_pushnumber(L,lua_upvalueindex(2));
    lua_pushnumber(L,upval1 + upval2);
    return 1;
}

然后向lua虚拟机注册一下全局函数

lua_register(L,"generatecclosure",generatecclosure);
lua_register(L,"generatecclosure2",generatecclosure2);

后执行main.lua:

c = generatecclosure() c2 = generatecclosure2() print(c()) -- 2 print(c()) -- 4 print(c2()) -- 22 print(c2()) -- 24

相关文章

1.github代码实践源代码是lua脚本语言,下载th之后运行thmai...
此文为搬运帖,原帖地址https://www.cnblogs.com/zwywilliam/...
Rime输入法通过定义lua文件,可以实现获取当前时间日期的功能...
localfunctiongenerate_action(params)localscale_action=cc...
2022年1月11日13:57:45 官方:https://opm.openresty.org/官...
在Lua中的table(表),就像c#中的HashMap(哈希表),key和...