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中的内容

发表评论