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

lua5.2模块注册

2015-09-13 00:43 411 查看
lua 5.2不鼓励使用luaL_register把模块注册到全局域,而是使用luaL_newlib。

我们首先看下luaL_newlib,它是一个宏,代码如下:

#define luaL_newlib(L,l)    (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))


luaL_newlibtable创建一个表放到栈顶,然后luaL_setfuncs把列表参数l中的函数名作为key,函数地址用来创建的闭包作为value插入到新建的table中,代码如下:

LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
for (; l->name != NULL; l++) {  /* fill the table with given functions */
int i;
for (i = 0; i < nup; i++)  /* copy upvalues to the top */
lua_pushvalue(L, -nup);
lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
lua_setfield(L, -(nup + 2), l->name);
}
lua_pop(L, nup);  /* remove upvalues */
}


luaL_setfuncs 函数在压入C闭包之前,把位于栈顶的nup个upvalue(外层函数局部变量)重新压栈,在创建C闭包的时候,存到C闭包的upvalue链表中。lua模块注册的时候,nup是0,故不用考虑upvalue入栈。C闭包入栈函数如下:

LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
lua_lock(L);
if (n == 0) {
setfvalue(L->top, fn);
}
else {
Closure *cl;
api_checknelems(L, n);
api_check(L, n <= MAXUPVAL, "upvalue index too large");
luaC_checkGC(L);
cl = luaF_newCclosure(L, n);
cl->c.f = fn;
L->top -= n;
while (n--)
setobj2n(L, &cl->c.upvalue
, L->top + n);
setclCvalue(L, L->top, cl);
}
api_incr_top(L);
lua_unlock(L);
}


如果没有upvalue,此时压入的是light C function,否则压入的是C closure。回到luaL_setfuncs函数,压栈闭包后,设置函数名和闭包(或者light C function)的键值对,最后删除栈顶的upvalue。

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