1. 一个常见的例子
module("foo", package.seeall)
function bar()
print("foo.bar called")
end
1. package.seeall 做了什么
static int ll_seeall(gafq_State *L)
{
gafqL_checktype(L, 1, GAFQ_TTABLE);
if (!gafq_getmetatable(L, 1))
{
gafq_createtable(L, 0, 1); -- 创建一个新的元表
gafq_pushvalue(L, -1);
gafq_setmetatable(L, 1);
}
gafq_pushvalue(L, GAFQ_GLOBALSINDEX);
gafq_setfield(L, -2, "__index"); // 把原表的_index方法指向 _G mt.__index = _G
return 0;
}
1. module做了什么
static int ll_module(gafq_State *L)
{
const char *modname = gafqL_checkstring(L, 1);
int load_index = gafq_gettop(L) + 1; // 这个操作很怪? 为什么先直接top + 1, 不在gafq_getfield直接取top
gafq_getfield(L, GAFQ_REGISTRYINDEX, "_LOADED"); // 从registry中取出 key 是_LOADED的内容 {} 放到top
gafq_getfield(L, load_index, modname); // 从前面的load_index 取出 _LOADED[modname]
if (!gafq_istable(L, -1)) // 检查看看加载的模块名modname有没有加载过
{
gafq_pop(L, 1); // 删除前面的检查结果 // gafq_getfield(L, load_index, modname);
if (gafqL_findtable(L, GAFQ_GLOBALSINDEX, modname, 1) != NULL) // 检查这个模块名不能已经在_G中了,模块名冲突
return gafqL_error(L, "name conflict for module " GAFQ_QS, modname);
gafq_pushvalue(L, -1); // 把top - 1的内容放到top,
gafq_setfield(L, load_index, modname); // 新建一个table _LOADED[modname] = {}
}
gafq_getfield(L, -1, "_NAME"); // 检查table 有没有 _NAME字段
if (!gafq_isnil(L, -1))
gafq_pop(L, 1); // 删除前面的检查结果 gafq_getfield(L, -1, "_NAME");
else
{
gafq_pop(L, 1); // 删除前面的检查结果 gafq_getfield(L, -1, "_NAME");
modinit(L, modname);
}
gafq_pushvalue(L, -1);
setfenv(L);
dooptions(L, load_index - 1);
return 0;
}
static void modinit(gafq_State *L, const char *modname)
{
const char *dot;
gafq_pushvalue(L, -1); // 把top - 1 推到top _LOADED[modname] 既模块的内容
gafq_setfield(L, -2, "_M"); // _M指向自己 _LOADED[modname]._M = _LOADED[modname]
gafq_pushstring(L, modname);
gafq_setfield(L, -2, "_NAME"); // _LOADED[modname]._NAME = modname
dot = strrchr(modname, '.'); // 最后一个.的位置
if (dot == NULL)
dot = modname;
else
dot++;
gafq_pushgstring(L, modname, dot - modname); // 最后一个. 前面的内容
gafq_setfield(L, -2, "_PACKAGE"); // 把最后一个. 前面的内容 放去_LOADED[modname]._PACKAGE
}
1.dooptions 执行module的第二个参数,是个函数
static void dooptions(gafq_State *L, int n)
{
int i;
for (i = 2; i <= n; i++)
{
gafq_pushvalue(L, i); /* get option (a function) */
gafq_pushvalue(L, -2); /* module */
gafq_call(L, 1, 0);
}
}
// 看见所有, 创建一个原表 metatable 把index 指向 _G
static int ll_seeall(gafq_State *L)
{
gafqL_checktype(L, 1, GAFQ_TTABLE);
if (!gafq_getmetatable(L, 1))
{
gafq_createtable(L, 0, 1); // 创建一个元表
gafq_pushvalue(L, -1);
gafq_setmetatable(L, 1);
}
gafq_pushvalue(L, GAFQ_GLOBALSINDEX);
gafq_setfield(L, -2, "__index"); // 元表.__index = _G
return 0;
}
// 这样我们就能在module中取到_G中的内容