您的位置:首页 > 编程语言 > Lua

lua c closure的使用

2016-01-14 19:16 531 查看
closure,闭包,即值和函数的绑定,本身也可作为函数调用,用于绑定的函数也可以称为函数模板。

闭包的关键在于绑定 值与函数,以及如何在函数中定位到这些绑定的值,这些值又叫upvalue。

每一个lua closure都有一个独立的闭包环境,宏 lua_upvalueindex(index) 可以获得第index个值的索引,藉由这些索引,可以对闭包内的upvalue读写。

1,创建闭包

关键函数是int lua_pushcclosure(lua_State *L,lua_CFunction func,int n ),其中n是堆栈顶端值得个数,这些值将复制到closure中,func是使用closure的函数,这个函数调用后会清除栈中n个值,会压入一个closure到栈中。

2,访问upvalue

当一个closure被调用,这个closure指定的函数就能通过upvalueindex索引访问所有upvalue。

比如:

int num=lua_tointeger(L,lua_upvalueindex(1));//获得第一个upvalue的值
int table_len=lua_objlen(L,upvalueindex(2));//获得第二个upvalue的长度
puts(lua_tostring(L,lua_upvalueindex(3)));//输出第三个upvalue


需要注意的是,upvalue的索引是和这些值压入顺序一致的。

修改一个upvalue:

lua_pushstring(L,"Hello");
lua_replace(L,lua_upvalueindex(1));//修改upvalue可以使用lua_replace函数,使用栈顶的值替换具体索引的值
3,代码例子

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#pragma comment(lib,"lua5.1.lib")
#pragma comment(lib,"lua51.lib")
<span style="font-family: Arial, Helvetica, sans-serif;">/*</span>
<span style="white-space:pre">		</span>文件名 3.c
<span style="white-space:pre">		</span>模块名 3
<span style="white-space:pre">			</span>Windows:3.dll
*/

#define l_typename(L,index) lua_typename(L,lua_type(L,index))

static int index_plus(lua_State *L){//正常的迭代器函数
int table_len=lua_objlen(L,lua_upvalueindex(1));
int index=lua_tointeger(L,lua_upvalueindex(2));

if(index>table_len){
lua_pushnil(L);
return 1;
}

lua_pushinteger(L,index+1);
lua_pushvalue(L,-1);
lua_replace(L,lua_upvalueindex(2));

lua_rawget(L,lua_upvalueindex(1));

return 1;
}

static int index_null(lua_State *L){//空的迭代器函数
lua_pushnil(L);
return 1;//return nil
}

static int make_index(lua_State *L){//生成迭代器
int top=lua_gettop(L);
int index;
if(LUA_TTABLE!=lua_type(L,1)){//第一个类型不是表
lua_pushcclosure(L,index_null,0);
return 1;
}
lua_pushvalue(L,1);
lua_pushinteger(L,lua_tointeger(L,2));
lua_pushcclosure(L,index_plus,2);
return 1;
}

int luaopen_3(lua_State *L){//引用这个库所调用的函数
lua_newtable(L);
lua_pushstring(L,"make_index");
lua_pushcfunction(L,make_index);
lua_rawset(L,-3);
return 1;
}


编译命令:

cl /LD 3.c out.def
其中out.def文件:

LIBRARY 3;
EXPORTS
luaopen_3 @1;


运行这个库的lua脚本:

local t=require '3'

for value in t.make_index{3,2,"这是","第一","次","发帖"} do
print(tostring(value))
end


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: