module 与 package.seeall

http://blog.codingnow.com/2006/02/lua_51_module.html

使用

module("test")

后,下面不再看的见前面的全局环境。如果在这个模块里想调用 print 输出调试信息怎么办呢?一个简单的方法是

local print=print
module("test")

这样 print 是一个 local 变量,下面也是可见的。或者可以用

local _G=_G
module("test")

那么 _G.print 也是可以用的。

当然还有一种巧妙的方式,lua 5.1 提供了一个 package.seeall 可以作为 module 的option 传入

module("test",package.seeall)

这样就 OK 了。至于它们是如何工作的,还是自己读源码会理解的清楚一些。

源码不太好读, 我们下面找文档和做实验来理解。

为啥使用了 package.seeall, 则此module就可以引用全局环境了呢?

文档:

http://www.lua.org/manual/5.1/manual.html

module (name [, ···])

This function can receive optional options after the module name, where each option is a function to be applied over the module.

package.seeall (module)

Sets a metatable for module with its __index field referring to the global environment, so that this module inherits values from the global environment. To be used as an option to function module.

使用package.seeall后, 会将当前module的环境表, 设置个 metatable( {__index=_G})

含义就是, 当你在module声明之后, 如果使用print函数, 则在当前module环境表中存在, 则会想_G表中搜索。

package.seeall

static int ll_seeall (lua_State *L) {
  luaL_checktype(L, 1, LUA_TTABLE);
  if (!lua_getmetatable(L, 1)) {
    lua_createtable(L, 0, 1); /* create new metatable */
    lua_pushvalue(L, -1);
    lua_setmetatable(L, 1);
  }
  lua_pushvalue(L, LUA_GLOBALSINDEX);
  lua_setfield(L, -2, "__index");  /* mt.__index = _G */
  return 0;
}

测试代码

module_test.lua

module(..., package.seeall)

local print = print
local getfenv = getfenv
local tostring = tostring
local getmetatable = getmetatable

--module("module_test")

local function printTable(tbl)

for k,v in pairs(tbl) do
        print("kay="..tostring(k) .. "  value="..tostring(v))
    end

end

varone = 1

local strkey = "vartwo"

-- 本模块环境
local env = getfenv(1)

env[strkey] = 2

print("vartwo="..vartwo)

print("getfenv(1) ="..tostring( ( getfenv(1) ) ) )

print("getfenv(1) metatable="..tostring( getmetatable( getfenv(1) ) ) )

print("--------------- before getmetatable( getfenv(1) ) -------------")
printTable( getmetatable( getfenv(1) ) )
print("--------------- after getmetatable( getfenv(1) ) -------------")

-- 调用此模块的环境
local env_caller = getfenv(2)

env["env_caller"] = env_caller

print("getfenv(2) ="..tostring(getfenv(2)))

main.lua

local testmodule = require("module_test")

var_caller = 55

print("testmodule.vartwo=" .. testmodule.vartwo)

local function printTable(tbl)

for k,v in pairs(tbl) do
        print("kay="..tostring(k) .. "  value="..tostring(v))
    end

end

print("----------- testmodule ------------------")

printTable(testmodule)

print("-----------  testmodule.env_caller ------------------")

printTable(testmodule.env_caller)

打印结果

>lua -e "io.stdout:setvbuf 'no'" "main.lua"
vartwo=2
getfenv(1) =table: 006F9438
getfenv(1) metatable=table: 006F92D0
--------------- before getmetatable( getfenv(1) ) -------------
kay=__index  value=table: 006F2650
--------------- after getmetatable( getfenv(1) ) -------------
getfenv(2) =table: 006F2650

testmodule.vartwo=2
----------- testmodule ------------------
kay=_NAME  value=module_test
kay=_PACKAGE  value=
kay=varone  value=1
kay=_M  value=table: 006F9438
kay=vartwo  value=2
kay=env_caller  value=table: 006F2650
-----------  testmodule.env_caller ------------------
kay=string  value=table: 006F9730
kay=xpcall  value=function: 006F6788
kay=module_test  value=table: 006F9438
kay=package  value=table: 006F7110
kay=tostring  value=function: 006F6968
kay=print  value=function: 006F6CC8
kay=os  value=table: 006F9848
kay=unpack  value=function: 006F6A08
kay=require  value=function: 006F7C98
kay=getfenv  value=function: 006F6E08
kay=setmetatable  value=function: 006F66A8
kay=next  value=function: 006F6C88
kay=assert  value=function: 006F6D48
kay=tonumber  value=function: 006F6888
kay=io  value=table: 006F96E0
kay=rawequal  value=function: 006F6DC8
kay=collectgarbage  value=function: 006F6D28
kay=arg  value=table: 006F92A8
kay=getmetatable  value=function: 006F6AE8
kay=module  value=function: 006F7B98
kay=rawset  value=function: 006F6AA8
kay=var_caller  value=55
kay=math  value=table: 006F96B8
kay=debug  value=table: 006F91E0
kay=pcall  value=function: 006F6CE8
kay=table  value=table: 006F7160
kay=newproxy  value=function: 006F0568
kay=type  value=function: 006F6A48
kay=coroutine  value=table: 006F7340
kay=_G  value=table: 006F2650
kay=select  value=function: 006F6B48
kay=gcinfo  value=function: 006F6D88
kay=pairs  value=function: 006F0538
kay=rawget  value=function: 006F6A88
kay=loadstring  value=function: 006F6B08
kay=ipairs  value=function: 006F2BD0
kay=_VERSION  value=Lua 5.1
kay=dofile  value=function: 006F6DE8
kay=setfenv  value=function: 006F6A28
kay=load  value=function: 006F6B88
kay=error  value=function: 006F6D68
kay=loadfile  value=function: 006F6DA8
>Exit code: 0

lua module package.seeall选项的更多相关文章

  1. Lua 学习之基础篇七<Lua Module,Package介绍>

    Lua 之Module介绍 包管理库提供了从 Lua 中加载模块的基础库. 只有一个导出函数直接放在全局环境中: [require]. 所有其它的部分都导出在表 package 中. require ...

  2. lua module环境探秘

    module 作用 module (name [, ···]) Creates a module. If there is a table in package.loaded[name], this ...

  3. lua --- Module

    首先需要明白,一般情况下,我们的定义的lua模块的文件与模块名(其实就是table的名字)是一致的,当然,不一致代码也是可以编译的(亲测),之所以这样,本人认为是为了实际项目中管理的方便.以下是定义模 ...

  4. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  5. python模块module package

    python模块module   package module package 常用模块 模块与包的区别 模块分为内置模块.第三方模块,自定义模块 程序会先从内置到第三方再到当前工作目录下去找你导入的 ...

  6. Python语法31[module/package+import]

    一 module 通常模块为一个文件,直接使用import来导入就好了.可以作为module的文件类型有".py".".pyo".".pyc" ...

  7. nginx install lua module

    #install luajit #http://luajit.org/download.html .tar.gz cd LuaJIT- make install PREFIX=/home/allen. ...

  8. Module, Package in Python

    1.To put it simple, Module是写好的一系列函数或变量,文件以.py为后缀,可以在其他Module中整体或部分引用. PS: 在Module中[结尾或开头]加入if __name ...

  9. NodeJS require a global module/package in linux

    https://stackoverflow.com/questions/15636367/nodejs-require-a-global-module-package 1  export NODE_P ...

随机推荐

  1. [题解+总结]动态规划大合集II

    1.前言 大合集总共14道题,出自江哥之手(这就没什么好戏了),做得让人花枝乱颤.虽说大部分是NOIP难度,也有简单的几道题目,但是还是做的很辛苦,有几道题几乎没思路,下面一道道边看边分析一下. 2. ...

  2. NOIP欢乐模拟赛 T3 解题报告

    3.小澳的葫芦 (calabash.cpp/c/pas) [题目描述] 小澳最喜欢的歌曲就是<葫芦娃>. 一日表演唱歌,他尽了洪荒之力,唱响心中圣歌. 随之,小澳进入了葫芦世界. 葫芦世界 ...

  3. Linux之线程管理

    linux下查看线程数的几种方法   1. cat /proc/${pid}/status [root@limt01 2325]# ps -ef|grep xinetd|grep -v grep ro ...

  4. winform退出或关闭窗体时弹窗提示代码:转

    winform退出或关闭窗体时弹窗提示代码,当我们点击窗体的 X 按钮时,会弹出一个对话框,询问我们是直接退出,还是最小化到托盘,还是取消这个行为.或是是否保存当前修改等等.以下以最小化到托盘为例. ...

  5. MongoDB设置访问权限、设置用户

    MongoDB已经使用很长一段时间了,基于MongoDB的数据存储也一直没有使用到权限访问(MongoDB默认设置为无权限访问限制),今天特地花了一点时间研究了一下,研究成果如下: 注:研究成果基于W ...

  6. 改进iOS客户端的升级提醒功能

    改进iOS客户端的升级提醒功能 功能设计 先申明一下,我是码农,不是一个产品经理,但我觉得现有市面上的很多 App,设计的 "升级提示功能" 都不太友好.在此分享一下我的想法,欢迎 ...

  7. TCP和UDP的聊天

    TCP聊天 TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议. 1.一个TCP连接必须要经过三次"对话"才能建立起来,其中的过程非 ...

  8. 多种方式实现在Android 手机上抓包

    一.素材来源 https://www.zhihu.com/question/20467503 二.方法整理 2.1 方式1:Packet Capture + HTTP Injector 使用于在手机端 ...

  9. odoo报表条码无法显示解决[转]

    当服务器为Linux(Ubuntu)时,ODOO打印的报表上是有条码的,却显示空白框框.问题在于服务器上没有安装条码的字体,reportlab渲染条码图形失败,导致显示不正常. 将附件中的字体下载,解 ...

  10. CentOS安装开发组相关的包

    yum groupinstall "Development Tools"   yum groupremove "Development Tools"