函数主要有 2 行,luaL_newlib 和 createmetatable 两个函数调用。LUAMOD_API int luaopen_string (lua_State *L) { luaL_newlib(L, strlib); createmetatable(L); return 1; }
#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, ...}
看起来很复杂,其实都是栈操作,真正做的事很少。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 */ }
然后,然后设置 meta_table 的 __index 属性为刚才创建的 strlib,大概像这样:G(L)->mt[ttypenv(obj)] = mt; /* mt 即为创建的 meta table,obj 空字符串,详细看代码*/
至此,strlib 加载完成,加载的结果,L->top -1 为一个 成员函数的 table。meta_table["__index"] = strlib
对于上面讲的 string lib 来讲,lua_call 调用的就是函数 luaopen_string,前两行为设置参数,具体调用细节不谈,调用的结果返回了一个 table。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 */ } }