Lua C Api lua c api 对栈的影响
Lua C API
void lua_createtable (lua_State *L, int narr, int nrec)
-
操作说明: 创建一个新的table,并把它放在栈顶。 narr 和 nrec 分别指定该 table 的 array 部分和 hash 部分的预分配元素数量
-
返回值:无
-
栈影响: 栈高+1,栈顶元素是新 table
-
注:
#define lua_newtable(L) lua_createtable(L, 0, 0)
常用这个
void lua_getfield (lua_State *L, int index, const char *k)
-
操作说明:
arr = Stack[index] // arr 是 table Stack.push( arr[k] )
取表中键为 k 的元素,这里的表是由 index 指向的栈上的一个表
-
返回值: 无
-
栈影响:栈高+1,栈顶元素是(Stack[index])[k]
-
注:该操作将触发 index 元方法
void lua_setfield (lua_State *L, int index, const char *k)
-
操作说明:
arr = Stack[index] arr[k] = Stack.top() Stack.pop()
给表中键为 k 的元素赋值 value (value就是栈顶元素), 这里的表是由 index 指向的栈上的一个表
-
返回值: 无
-
栈影响:高度-1,被弹出的是value
-
注: 该操作将触发 newindex 元方法
void lua_gettable (lua_State *L, int index)
-
操作说明:
ele = Stack[index] key = Stack.top() Stack.pop() value = ele[key] Stack.push(value)
根据 index 指定取到相应的表; 取栈顶元素为 key, 并弹出栈; 获取表中 key 的值压入栈顶。
-
返回值:无
-
栈影响:
高度不变, 但是发生了一次弹出和压入的操作, 弹出的是key, 压入的是value
-
注:将触发 index 元方法
void lua_settable (lua_State *L, int index)
-
操作说明:
ele = Stack[index] value = Stack.top() Stack.pop() key = Stack.top() Stack.pop() ele[key] = value
根据index指定取到相应的表; 取栈顶元素做value,弹出之; 再取当前栈顶元素做key,亦弹出之; 然后将表的键为key的元素赋值为value
-
返回值: 无
-
栈影响:高度-2, 第一次弹出value, 第二次弹出key
-
注: 该操作将触发 newindex 元方法
void lua_rawget (lua_State *L, int index)
-
操作说明:和 lua_gettable 操作一样,但是不触发相应的元方法
-
意义:TODO
void lua_rawgeti(lua_State *L, int index, int n)
-
操作说明
ele = Stack[index] value = ele[n] Stack.push(value)
-
返回值:无
-
栈影响:栈高+1, 栈顶新增元素就是 value
-
注:不触发相应的元方法
void lua_rawset (lua_State *L, int index)
- 操作说明:和 lua_settable 操作一样,但是不触发相应的原方法
void lua_rawseti (lua_State *L, int index, int n)
-
操作说明:
ele = Stack[index] value = Stack.top() Stack.pop() ele[n] = value
-
返回值:无
-
栈影响:-1, 栈顶将value弹出
-
注:不触发相应的元方法
void lua_pushvalue (lua_State *L, int index)
-
操作说明:
value = Stack[index] Stack.push(value)
-
返回值:无
-
栈影响:栈高 +1
int luaL_newmetatable (lua_State *L, const char *tname)
- 操作说明:
-
在注册表中查找tname,如果已经注册,就返回0,否者继续, 并平栈
lua_getfield(L, LUA_REGISTRYINDEX, tname) if (!lua_isnil(L, -1)) return 0; lua_pop(L, 1);
-
创建一个表,并注册,返回1
lua_newtable(L) lua_pushvalue(L, -1) lua_setfield(L, LUA_REGISTRYINDEX, tname) return 1
相当于在注册表中有 {tname:栈顶的table} 的键值对。
-
-
返回值:已注册,就返回0;未注册,创建表后,返回1
- 栈影响:栈高 +1,栈顶元素是在注册表中注册过的新表
void *lua_newuserdata (lua_State *L, size_t size)
-
操作说明
该函数分配一块由size指定大小的内存块, 并放在栈顶
-
返回值:新分配的块的地址
-
栈影响:栈高+1, 栈顶是userdata
-
注:userdata用来在lua中表示c中的值. 一个完整的userdata有自己的元表, 在垃圾回收时, 可以调用它的元表的__gc方法
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n)
-
操作说明:
向栈上压一个C闭包。当一个c函数被创建时, 可以绑定几个值在它上面, 从而形成一个闭包. 在任何时刻调用这个c函数时, 都可以访问这几个绑定值.
绑定的方法: 先一次压入要绑定的n个值到栈上, 然后调用lua_pushcclosure(L, fn, n)这样就形成的一个c闭包
-
返回值:无
-
栈影响:栈高 –(n - 1) , 一共弹出n个元素(及那些绑定的值), 压入一个cclosure
-
注
#define lua_pushcfunction(L, f) lua_pushcclosure(L, f, 0) #define lua_register(L, n, f) (lua_pushcfunction(L, f), lua_setglobal(L, n))
这个是比较常用的, 以n为lua中的key压入一个0个绑定值的cclosure.
void lua_call(lua_State* L, int nargs, int nresults)
-
操作说明
argn = Stack.push() ... // 一共压入nargs个参数 arg2 = Stack.pop() arg3 = Stack.pop() func = Stack.pop() // 函数本身也弹出 res1, res2, ..., resj = func(arg1, arg2, ..., argn) Stack.push(res1) Stack.push(res2) … // 压入nresults个返回值 Stack.push(resj)
-
返回值:无
-
栈影响:
调用结束后,栈高度增加 nresults – (1 + nargs),如果将 nresults 参数设置为LUA_MULTRET,那么lua返回几个值,栈上就压入几个值,否者强制压入 nresults 个值,不足的是空值,多余的抛弃掉
-
注: 这个函数是有危险的,如果在其中发生了错误,会直接退出程序
int lua_pcall(lua_State* L, int nargs, int nresults, int errfunc)
-
操作说明:
参数, 行为和 lua_call 都一样, 如果在调用中没有发生任何错误, lua_pcall == lua_call; 但是如果有错误发生时, lua_pcall会捕获它 errfunc指出了 Stack 上的一个元素, 这个元素应该是一个函数, 当发生错误的时候
ef = Stack[errfunc] value = ef(errmsg) Stack.push(value)
也就是说, 在错误的时候, errfunc指定的错误处理函数会被调用, 该处理函数的返回值被压到栈上.
默认情况下, 可以给errfunc传值 0, 实际的效果是指定了这样一个函数做出错处理 function defaulterr(errmsg) return errmsg end.
-
注
本函数有返回值 LUA_ERRRUN运行时错误 LUA_ERRMEM内存分配错误[注意, 这种错会导致lua调用不了错误处理函数] LUA_ERRERR运行错误处理函数时出错了, 写程序的时候必须检查返回值:)
强烈推荐该函数, 不过事实上大家也都用的这个函数:)
TODO
void lua_register (lua_State *L, const char *name, lua_CFunction f)
- 注 #define lua_register(L,n,f) \ (lua_pushcfunction(L, f), lua_setglobal(L, n))
void lua_setglobal (lua_State *L, const char *name);
void lua_getglobal (lua_State *L, const char *name);
- Pushes onto the stack the value of the global name.
void lua_getglobal (lua_State *L, const char *name);
- Pushes onto the stack the value of the global name.
void luaL_register (lua_State *L,
const char *libname,
const luaL_Reg *l);
Opens a library.
When called with libname equal to NULL, it simply registers all functions in the list l (see luaL_Reg) into the table on the top of the stack.
When called with a non-null libname, luaL_register creates a new table t, sets it as the value of the global variable libname, sets it as the value of package.loaded[libname], and registers on it all functions in the list l. If there is a table in package.loaded[libname] or in variable libname, reuses this table instead of creating a new one.
In any case the function leaves the table on the top of the stack.
练习:
int luaopen_lua_map(lua_State *l)
{
const struct luaL_Reg _obj[] = {
{"new", lua_map::new_object},
{"__gc", lua_map::finalize},
//{"insert",lua_map::insert},
{"__newindex",lua_map::insert},
{"erase",lua_map::erase},
//{"size", lua_map::size},
{"__len", lua_map::size},
{"show", lua_map::show},
{"stack_test",lua_map::tc_stack},
{"finalize", lua_map::finalize},
{NULL, NULL}
};
//[{}]
luaL_newmetatable(l, lua_map::type_id);
//[{"new":lua.....}]
luaL_register(l, NULL, _obj);
//{"new":lua.....}
//{"new":lua.....}
lua_pushvalue(l, -1);
//{"new":lua.....}
//{"new":lua....,__index:{"new":lua.....}
//{"new":lua....,__index:{"new":lua.....}}
lua_setfield(l, -2, "__index");
//{}
//{"new":lua....,index:{"new":lua.....}}
lua_newtable(l);
//{"new":lua....,index:self}
//{}
//{"new":lua....,index:self}]
lua_pushvalue(l, -2);
//{"new":lua....,index:self}
//{lua_map:{"new":lua....,index:self},"new":lua....,index:self}
//{"new":lua....,index:self}
//[{lua_map:{"new":lua....,index:self},"new":lua....,index:self}
//{"new":lua....,index:self}]
lua_setfield(l, -2, "lua_map");
//[{lua_map:{"new":lua....,index:self},"new":lua....,index:self}
//{lua_map:{"new":lua....,index:self},"new":lua....,index:self}]
lua_pushvalue(l, -1);
//{map:{lua_map:{"new":lua....,index:self},"new":lua....,index:self}
lua_setglobal(l, "map");
return 1;
}