注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

偶有所得,记录在此

有分享交流才有进步,永远不要固步自封

 
 
 

日志

 
 

Lua lib 加载分析  

2012-08-02 18:27:39|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

String Lib 加载部分
-----------------------------
以 string lib 为例,加载代码如下:

LUAMOD_API int luaopen_string (lua_State *L) {
luaL_newlib(L, strlib);
createmetatable(L);
return 1;
}

函数主要有 2 行,luaL_newlib 和 createmetatable 两个函数调用。

luaL_newlib 被定义为宏,完成功能很简单。首先创建一个 table,然后把成员函数名做 key,成员函数作为 value 放入该 table 中,over。
#define luaL_newlibtable(L,l)   \
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)

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


luaL_newlib,L-top - 1 即为刚才创建的 table,结果大概像下面这样:

strlib = {"byte"=str_byte, "gmatch"=gmatch, ...}


createmetatable 函数:

static void createmetatable (lua_State *L) {
lua_createtable(L, 0, 1); /* table to be metatable for strings */
lua_pushliteral(L, ""); /* dummy string */
lua_pushvalue(L, -2); /* copy table */
lua_setmetatable(L, -2); /* set table as metatable for strings */
lua_pop(L, 1); /* pop dummy string */
lua_pushvalue(L, -2); /* get string library */
lua_setfield(L, -2, "__index"); /* metatable.__index = string */
lua_pop(L, 1); /* pop metatable */
}

看起来很复杂,其实都是栈操作,真正做的事很少。
首先,创建一个 table(假定名字为 meta_table),然后挂接到全局 meata table 映射表(G(L)->mt)里面,key 为类型名,这里是 string 类型的 int 值;挂接动作是在 lua_setmetatable 函数里面完成:

G(L)->mt[ttypenv(obj)] = mt; /* mt 即为创建的 meta table,obj 空字符串,详细看代码*/

然后,然后设置 meta_table 的 __index 属性为刚才创建的 strlib,大概像这样:

meta_table["__index"] = strlib

至此,strlib 加载完成,加载的结果,L->top -1 为一个 成员函数的 table。

lib 的注册
-------------
最上层加载某一个库时,调用的函数是 luaL_requiref,如下:

LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
lua_CFunction openf, int glb) {
lua_pushcfunction(L, openf);
lua_pushstring(L, modname); /* argument to open function */
lua_call(L, 1, 1); /* open module */
luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED");
lua_pushvalue(L, -2); /* make copy of module (call result) */
lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
lua_pop(L, 1); /* remove _LOADED table */
if (glb) {
lua_pushvalue(L, -1); /* copy of 'mod' */
lua_setglobal(L, modname); /* _G[modname] = module */
}
}

对于上面讲的 string lib 来讲,lua_call 调用的就是函数 luaopen_string,前两行为设置参数,具体调用细节不谈,调用的结果返回了一个 table。

luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED")
_LOADED 对应一个 table,用来存储模块的加载结果。key 为模块名(对应刚才的为 string),value 为成员函数的 table,luaL_getsubtable 后面2行就是干这事的。

最后 3 行,如果是模块为全局作用域,再扔到注册表的全局变量中。
  评论这张
 
阅读(1640)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017