lua 之 全局变量
2021/12/22 6:23:42
本文主要是介绍lua 之 全局变量,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
注:本篇文章从个人博客园移植而来
_G
lua的全局变量保存在一个常规的table中,这个table被称为全局环境,该table存储在名为 _G 的表中
for i, v in pairs(_G) do print(i) end --[[ -- 为了方便查看,进行了缩行 rawequal getmetatable bit32 load dofile pairs table package loadfile io xpcall print type _G debug rawlen tostring error assert rawget require math select next utf8 coroutine _VERSION arg string os rawset tonumber collectgarbage setmetatable pcall ipairs ]] --[[ -- 整理了部分,方便大家学习Lua C相关 ------------------ lbaselib.c中 ------------------ 参考文件网址:http://www.lua.org/source/5.3/lbaselib.c.html assert collectgarbage dofile error getmetatable ipairs loadfile load next pairs pcall print rawequal rawget rawset select setmetatable tonumber tostring type xpcall _G _VERSION ------------------ loadlib.c中 ------------------ 参考文件网址:http://www.lua.org/source/5.3/loadlib.c.html require module ------------------ lualib.h 中 ------------------ 参考文件网址:http://www.lua.org/source/5.3/lualib.h.html coroutine table io os string math debug package ------------------ lstrlib.h 中 ------------------ 参考文件网址:http://www.lua.org/source/5.3/lstrlib.c.html unpack ]]
全局变量不需要声明即可使用,然而打字出错的情况可能会导致程序出现难以发现的bug。
因此我们可以添加一个对全局表不存在健的访问,提高程序的健全性:
print(g_A) -- nil 可能会导致程序出现难以发现的bug -- 推荐方式 setmetatable(_G, { -- 写入变量 __newindex = function(_, n) error("attempt to write to undeclared variable " .. n, 2) end, -- 读取变量 __index = function(_, n) error("Error: attempt to read undeclared variable " .. n, 2) end, }) print(g_A) -- Error:attempt to read undeclared variable g_A
Lua虚拟机
在Lua虚拟机中,用一个全局结构的global_State来管理多个lua_State。
在调用luaL_newstate时,创建一个全局的global_State和一个lua_State后,luaL_newstate会调用f_luaopen,然后f_luaopen调用init_registry来初始化注册表。
/* ** Create registry table and its predefined values ** 在lstate.c中,参考代码网址:http://www.lua.org/source/5.1/lstate.c.html */ static void init_registry (lua_State *L, global_State *g) { TValue temp; /* 创建注册表,初始化注册表数组部分大小为LUA_RIDX_LAST */ Table *registry = luaH_new(L); sethvalue(L, &g->l_registry, registry); luaH_resize(L, registry, LUA_RIDX_LAST, 0); /* 把这个注册表的数组部分的第一个元素赋值为主线程的状态机L 这里所说的线程并非是os的线程,而是lua的状态机概念 */ /*即 registry[LUA_RIDX_MAINTHREAD] = L */ setthvalue(L, &temp, L); /* temp = L */ luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); // 把注册表的数组部分的第二个元素赋值为全局表 /*即 registry[LUA_RIDX_GLOBALS] = table of globals */ /* temp = new table (global table) */ sethvalue(L, &temp, luaH_new(L)); luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); }
在创建注册表后,会将全局表注册到脚本中。
// 在linit.c中,参考代码网址:http://www.lua.org/source/5.1/linit.c.html static const luaL_Reg loadedlibs[] = { {"_G", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, {LUA_COLIBNAME, luaopen_coroutine}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_UTF8LIBNAME, luaopen_utf8}, {LUA_DBLIBNAME, luaopen_debug}, #if defined(LUA_COMPAT_BITLIB) {LUA_BITLIBNAME, luaopen_bit32}, #endif {NULL, NULL} };
以luaopen_base为例,会吧脚本用的函数注册到全局表,代码如下:
// 相关的函数表 static const luaL_Reg base_funcs[] = { {"assert", luaB_assert}, {"collectgarbage", luaB_collectgarbage}, {"dofile", luaB_dofile}, {"error", luaB_error}, {"getmetatable", luaB_getmetatable}, {"ipairs", luaB_ipairs}, {"loadfile", luaB_loadfile}, {"load", luaB_load}, /* 省略了部分代码*/ {"_G", NULL}, {"_VERSION", NULL}, {NULL, NULL} }; // LUAMOD_API int luaopen_base (lua_State *L) { /* open lib into global table */ lua_pushglobaltable(L); luaL_setfuncs(L, base_funcs, 0); /* set global _G */ lua_pushvalue(L, -1); lua_setfield(L, -2, "_G"); /* set global _VERSION */ lua_pushliteral(L, LUA_VERSION); lua_setfield(L, -2, "_VERSION"); return 1; }
参考:深入理解Lua的全局变量_G以及源码实现
这篇关于lua 之 全局变量的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-01Java部署教程:新手入门指南
- 2024-11-01Java部署教程:从入门到实践
- 2024-11-01Java订单系统教程:新手入门指南
- 2024-11-01Java分布式教程:新手入门指南
- 2024-11-01Java管理系统教程:新手入门详解
- 2024-11-01Java监控系统教程:从入门到实践
- 2024-11-01SpringCloud Alibaba入门:轻松搭建微服务架构
- 2024-11-01Swagger入门:新手必读指南
- 2024-11-01Swagger入门:轻松搭建API文档
- 2024-11-01uni-APP入门:新手快速上手指南