关于lua的闭包(Closure)和Upvalue

关于lua的闭包(Closure)和Upvalue

关于lua的闭包(Closure)和Upvalue

upvalue:嵌套函数的外部函数的局部变量

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



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, upval2;    upval1 = lua_tonumber(L, lua_upvalueindex(1));    upval2 = lua_tonumber(L, lua_upvalueindex(2));    upval1++; upval2++;    lua_pushnumber(L, upval1); lua_replace(L, lua_upvalueindex(1));    lua_pushnumber(L, upval2); lua_replace(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()) -- 2print(c()) -- 4print(c2()) -- 22print(c2()) -- 24

推荐阅读