您的位置:首页 > 娱乐 > 明星 > 简单的微信小程序项目_网站推广意识薄弱_网盘搜索引擎入口_色盲测试图看图技巧

简单的微信小程序项目_网站推广意识薄弱_网盘搜索引擎入口_色盲测试图看图技巧

2025/2/24 9:30:21 来源:https://blog.csdn.net/sindyra/article/details/144169365  浏览:    关键词:简单的微信小程序项目_网站推广意识薄弱_网盘搜索引擎入口_色盲测试图看图技巧
简单的微信小程序项目_网站推广意识薄弱_网盘搜索引擎入口_色盲测试图看图技巧

一、global_State,lua_State与G表

Lua支持多线程环境,使用 lua_State 结构来表示一个独立的 Lua 线程(或协程)。每个线程都需要一个独立的全局环境。而lua_State 中的l_G指针,指向一个global_State结构,这个就是我们常说的G表,也就是一个全局变量和虚拟机全局资源的集合。

struct lua_State {CommonHeader;lu_byte status;StkId top;  /* first free slot in the stack */StkId base;  /* base of current function */global_State *l_G;CallInfo *ci;  /* call info for current function */const Instruction *savedpc;  /* `savedpc' of current function */StkId stack_last;  /* last free slot in the stack */StkId stack;  /* stack base */CallInfo *end_ci;  /* points after end of ci array*/CallInfo *base_ci;  /* array of CallInfo's */int stacksize;int size_ci;  /* size of array `base_ci' */unsigned short nCcalls;  /* number of nested C calls */unsigned short baseCcalls;  /* nested C calls when resuming coroutine */lu_byte hookmask;lu_byte allowhook;int basehookcount;int hookcount;lua_Hook hook;TValue l_gt;  /* table of globals */TValue env;  /* temporary place for environments */GCObject *openupval;  /* list of open upvalues in this stack */GCObject *gclist;struct lua_longjmp *errorJmp;  /* current error recover point */ptrdiff_t errfunc;  /* current error handling function (stack index) */
};

下面看看global_State,它是 Lua 虚拟机全局的状态结构体,存储了与整个 Lua 虚拟机相关的全局数据和资源。它是为整个 Lua 实例共享的数据结构,而非单个线程或协程。

typedef struct global_State {stringtable strt;  /* hash table for strings */lua_Alloc frealloc;  /* function to reallocate memory */void *ud;         /* auxiliary data to `frealloc' */lu_byte currentwhite;lu_byte gcstate;  /* state of garbage collector */int sweepstrgc;  /* position of sweep in `strt' */GCObject *rootgc;  /* list of all collectable objects */GCObject **sweepgc;  /* position of sweep in `rootgc' */GCObject *gray;  /* list of gray objects */GCObject *grayagain;  /* list of objects to be traversed atomically */GCObject *weak;  /* list of weak tables (to be cleared) */GCObject *tmudata;  /* last element of list of userdata to be GC */Mbuffer buff;  /* temporary buffer for string concatentation */lu_mem GCthreshold;lu_mem totalbytes;  /* number of bytes currently allocated */lu_mem estimate;  /* an estimate of number of bytes actually in use */lu_mem gcdept;  /* how much GC is `behind schedule' */int gcpause;  /* size of pause between successive GCs */int gcstepmul;  /* GC `granularity' */lua_CFunction panic;  /* to be called in unprotected errors */TValue l_registry;struct lua_State *mainthread;UpVal uvhead;  /* head of double-linked list of all open upvalues */struct Table *mt[NUM_TAGS];  /* metatables for basic types */TString *tmname[TM_N];  /* array with tag-method names */
} global_State;

再进一步讲,lua_state 是暴露给用户的数据类型,既表示一个 lua 程序的执行状态,也指代 lua 的一个线程(在官方文档中)。每个线程拥有独立的数据栈以及函数调用栈,还有独立的调试钩子和错误处理设置。所以我们不应当简单的把lua_state 看成一个静态的数据集,它是一个lua 线程的执行状态。所有的lua C API 都是围绕这个状态机:
或把数据压入堆栈,或取出,或执行栈顶的函数,或继续上次被中断的执行过程。

从 lua 的使用者的角度看,global_state 是不可见的。我们无法用公开的 api 取到它的指针,也不需要引用它。但分析lua 的实现就不能绕开这个部分。
global_state  里面有对主线程的引用,有注册表管理所有全局数据,有全局字符串表,有内存管理函数,有GC 需要的把所有对象串联起来的相关信息,以及一切 lua 在工作时需要的工作内存。

二、_ENV 是什么

_ENV其实代表的是当前函数的环境,一个环境就是一个表,该函数被限定为只能访问该表中的域,或在函数体内自己定义的变量。

在 Lua 中,会为每个代码段增加一个预定义上值,即 _ENV 。他是一个外部局部变量,会将代码段中使用的 “全局变量” 存在这个 _ENV 中。

Lua 编译器会将以下代码段进行转换,全局变量都会被带上 _ENV

local i = 10
j = 100
k = j + i
print(i, j, k)

会被转换为

local i = 10
_ENV.j = 100
_ENV.k = _ENV.j + i
print(i, _ENV.j, _ENV.k)

 对于上面的代码段, _ENV 的存在点,可以理解为如下

local _ENV = 初始化
return function (...)local i = 10_ENV.j = 100_ENV.k = _ENV.j + iprint(i, _ENV.j, _ENV.k)
end

这里可以注意到 _ENV 是一个代码段外部的局部变量 ,但是他会进行初始化,理论上他可以是任意的表,但是为了维护全局的概念,所以这里会使用 _G 进行初始化,这样就让我们无感知的使用到了全局。

我们可以将 _ENV 和 _G 进行打印,在不进行修改的情况下,_ENV 和 _G 两者其实都是同一个表

doprint(_ENV, _G)     --> table: 0x6000007d4200	table: 0x6000007d4200
end
那么我们通常去查找一个全局变量时,其实是在当前函数环境,也就是当前函数的env表中查找(准确来说是到函数对应的Closure(闭包)指针中的env表去查询数据)。这里提到的“当前函数环境”,指的不一定是某一个具体的函数,也可能是一个 Lua文件。
早期的Lua 提供了几个 API 来读取当前函数的环境,分别是 getfenv和 set env
因此,如果执行以下代码:
setfenv(1,{})
print(a)
实际上找不到 Lua 标准库提供的 print 函数,并且会提示报错 attempt to call global ’print’(a  nil
value )。 原因就是首先使用 setfenv将当前函数的env表置为一个空表 , env 表中查找不到这个名字的函数。
下面来看看函数的 env 表是如何创建的 在创建一个 Closure 对象时,都会调用 getcurrenv
函数来获取当前的环境表:
(lapi.c) 
79 static Table *getcurrenv (lua_State *L) { 
80     if (L- >ci == L- >base_ci) /* no enclosing function? */ 
81         return hvalue(gt(L)); /* use global table as environment */ 
82     else { 
83         Closure unc = curr_func(L); 
84         return func ->c.env; 
85     } 
86 }
它将区分如下两种情况。
1.如果该函数不是内嵌函数,那么直接返回G表
2.否则,如果是内嵌函数,就返回其母函数的 env表
在创建一个新的Closure(闭包) 时,会调用这个函数返回的结果,对新的 Closure 的环境进行赋值
这里可以看出, env 表会逐层继承。

三、Lua的热更

理解了ENV,热更部分可以先参考Lua 的代码加载和热更新方式

未完待续...

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com