Lua5.1 升级 Lua5.3 升级 小结
Lua的版本差异确实是比较让人头疼的事情,之前在移动端一直采用Android下使用LuaJit,Ios下使用Lua5.1。这次升级到Xlua(lua5.3版本)主要有两方面的原因:一是ulua后续维护比价差,决定要升级到xlua,另一方面是公司在上线检查中提示禁止Luajit的使用(一些Crash无法解决),当然顺便解决了bit、64位问题。
1. 改变
参考:5.1 到 5.2 、5.2 到 5.3 、云风:Lua 5.2 的细节改变
2. Module
5.2中抛弃module,建议使用require进行加载, 可能是考虑到Module定义对全局表的污染, 参考:抵制使用 module() 定义模块
解决方案:
- 通过luaconf.h.in中LUA_COMPAT_MODULE宏定义打开兼容支持
- 在Lua中自定义,如下:
local base = _ENV
local modname = {}
local _ENV = modname
...
return modname
3. setfenv/getfenv
在5.1版本,可以理解为每个chunk都具有自己的环境表,然后通过setfenv/getfenv进行设置和操作。Lua5.2开始取消了环境表的概念,取消setfenv/getfenv方法,增加了_Env来管理。
_ENV
- _Env作为chunk‘闭包的第一个upvalue,从 load 开始(初始化为_G),第一个 chunk 就被加上了 _ENV 这个 upvalue ,然后依次传递下去。
- 如果在某个chunk'中定义 local _ENV={...}其实就相当于修改这个chunk下面的环境。
- Lua在编译时会给变量名var变为_ENV.var,
-- Lua 5.1
function foobar()
setfenv(1, {})
-- code here
end
-- Lua 5.2
function foobar()
local _ENV = {}
-- code here
end
_G 和 _Env*
_G 是放在注册表LUA_RIDX_GLOBALS中,初始化时核心的库都放在_G中;_Env 是chunk闭包的第一个upvalue,load时默认为_G, 然后后面定义的变量都会在编译时加上_ENV.前缀,以此传递下去,当然也可以修改。lua的注册表,_ENV,_G 底层实现从源代码层级对二者之间的区别进行了讨论。如果想要修改环境的同时还能访问全局变量
a = 1
local newgt = ()
setmetatable(newgt, {__index = _G})
_ENV = newgt
print(a) --> 1
a = 10
print(a) --> 10
print(_G.a) --> 1
_G.a = 20
print(_G.a) --> 20
Lua5.3 实现 SetFenv/GetFenv
5.2开始在Debug 类中提供了一些列关于upvalue操作的函数,通过这个方法可以实现类似5.1中setfenv/getfenv的操作方式。详细的过程可以参考 这两篇文章:
Implementing setfenv in Lua 5.2, 5.3, and above
Converting setfenv getfenv to Lua 5.2
local function getfenv(fn)
local i = 1
while true do
local name, val = debug.getupvalue(fn, i)
if name == "_ENV" then
return val
elseif not name then
break
end
i = i + 1
end
end
local function setfenv(fn, env)
local i = 1
while true do
local name = debug.getupvalue(fn, i)
if name == "_ENV" then
debug.upvaluejoin(fn, i, (function()
return env
end), 1)
break
elseif not name then
break
end
i = i + 1
end
return fn
end
4. 全局注册表
在5.2中已经移除了LUA_GLOBALSINDEX,去而带之的是注册表。5.2以后中上面两个函数都是使用的注册标中的LUA_RIDX_GLOBAS伪索引(索引注册表的全局环境)。处理 lua和C交互API的时候需要注意
5. luaL_register
Lua5.2 以后取消了这个接口,不过可以通过luaL_setfunc方法看来实现
#undef luaL_register
#define luaL_register(L,n,f) \
{ if ((n) == NULL) luaL_setfuncs(L,f,0); else luaL_newlib(L,f); }
#endif
6. 64位支持
Lua5.3 默认支持64位整数和浮点数,当然也可以通过luaconf.h修改为32位。默认为64位之后徐需要注意的是:
- 原先的一些数学计算规则有些修改,至少碰到64位大数据除法溢出的问题,比如:local H3 = 0xffffffffffffff / 0x100000000,或者 math.random 如果传入浮点数会报错,需要调用math.floor 进行转化
- 原先使用外部库进行64位数据处理可以转换到现有处理方式,b特别是以前5.1版本下protobuf的类库
7. 小结
从luajit升级到5.3版本问题都比较零碎,除了上面几个问题,还包括:
- lua源代码不平台版本编译(仅限不熟悉编译的人)
- lua-pb支持5.3 64位数据、替换struct、bit类库等,当然你也可以直接换个库
github上也可以找到一些实现好的类库来满足不同版本之间的兼容,比如:Lua向下兼容github 库、Lua不同版本间兼容资源
参考
lua的注册表,_ENV,_G 底层实现
抵制使用 module() 定义模块
云风 lua 5.2 的 _ENV
对lua中_ENV表的理解
Env环境
Implementing setfenv in Lua 5.2, 5.3, and above
Converting setfenv getfenv to Lua 5.2
Lua向下兼容github 库
Lua不同版本间兼容资源
Lua5.1 升级 Lua5.3 升级 小结的更多相关文章
- Web工程软件升级之数据库升级(一)
1. 首先检查oracle数据库版本是否正确 (可以使用方法 lsinventory来实现) 2. 检查oracle连接是否成功 3. 解压升级包,放到特定目录 4. 做升级前数据备份,备份主要业务数 ...
- Android应用程序的自动更新升级(自身升级、通过tomcat)(转)
Android应用程序的自动更新升级(自身升级.通过tomcat) http://blog.csdn.net/mu0206mu/article/details/7204746 刚入手android一个 ...
- 采用MySQL_upgrade升级授权表方式升级
1.7.1 采用MySQL_upgrade升级授权表方式升级(1) 这种升级方式比较省事,通过MySQL_upgrade命令即可完成.下面来演示一下整个升级过程. 1)修改my.cnf配置文件,因为M ...
- django升级2.1python升级3.7时出现的错误:"trying to load '%s': %s" % (entry[1], e) django.template.library.InvalidTemplateLibrary:
django升级2.1python升级3.7时出现如下的错误: "trying to load '%s': %s" % (entry[1], e) django.template. ...
- 4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(远程升级WIFI内部程序)
https://www.cnblogs.com/yangfengwu/p/10360618.html 演示视频: https://www.bilibili.com/video/av54894356/ ...
- weblogic 升级bsu_Weblogic补丁升级之坑坑洼洼
转至:https://blog.csdn.net/weixin_30682635/article/details/111911952 [概述] 虽然当前国内去IOE波涛汹涌,但不可否认OracleWe ...
- Web工程软件升级之数据库升级(二)
升级前检查 1. 用户是否存在 awk -F: '{if($1 == "xxx") print $1}' /ect/passwd 用户名 awk -F: '{if($1 == &q ...
- MySQL升级-5.6升级到5.7版本&切换GTID模式
目前未在生产环境中升级过数据库版本,倒是在测试环境跟开发环境升级过. 可以通过mysqldump sql文件进行升级,也可以通过mysql_upgrade升级,前者耗时较长,且 ...
- 6-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇-优化升级(安装Apache (Web服务器)软件,测试HTTP)
为了和SDK升级保持协议一致,花了两天时间实现了用LUA开发,MQTT+HTTP方式实现远程升级 安装Apache主要是为了实现通过HTTP下载资源 升级介绍: 0,用户点击检查更新时,APP首先通过 ...
随机推荐
- IE的浏览器模式、文本模式
最近在部署网页的时候,发现IE下的布局完成混乱. 在改变IE的文本模式后,显示就正常了. IE的浏览器模式,用于切换IE针对该网页的默认文本模式.对不同版本浏览器的条件注释解析.决定请求头里userA ...
- 业务开发(一)—— MySQL
0x01.SQL异常Incorrect string value java.sql.SQLException: Incorrect string value: '\xE6\x88\x91\xE7\x9 ...
- Python爬虫之提取Bing搜索的背景图片并设置为Windows的电脑桌面
鉴于现阶段国内的搜索引擎还用不上Google, 笔者会寻求Bing搜索来代替.在使用Bing的过程中,笔者发现Bing的背景图片真乃良心之作,十分赏心悦目,因此,笔者的脑海中萌生了一个念头:能否自 ...
- [android] 测试的相关概念
/********************2016年5月4日 更新********************************/ 知乎:如何专业地进行黑盒测试? 之前遇到过有些黑盒测试人员,感觉他 ...
- LINUX sed grep awk之间比较整理
正则表达式基础 在最简单的情况下,一个正则表达式看上去就是一个普通的查找串.例如,正则表达式"testing"中没有包含任何元字符,,它可以匹配"testing" ...
- Android LiveData使用
LiveData是一个可观察的数据持有者类. 与常规observable不同,LiveData是生命周期感知的,当生命周期处于STARTED或RESUMED状态,则LiveData会将其视为活动状态, ...
- String的坑
想必大家在熟悉不过了,不错今天就遇到了这个万年坑,哪怕喜欢翻源码的人,也不屑一顾翻它的源码,良言相劝最好翻下源码. 1. String为啥被定义为final ? 2. String是线程安全的么 ...
- 自定义mvc或mtv框架:基于wsgiref的web框架
把mvc或mtv框架的model数据库,view:html,control逻辑处理,url判别,wsgiref集中在一个文件 代码如下 #!/usr/bin/env python #-*- codin ...
- [工具配置]requirejs 多页面,多入口js文件打包总结
需要明确以下几点: 1.本地前端调试代码肯定是调用原始的路径以及代码,但是线上运行的肯定是通过打包后的另一个路径,这儿就是生成的dist文件夹了. 2.requirejs的引入,线上跟线下的路径怎么控 ...
- CSS3效果:animate实现点点点loading动画效果(一)
实现如图所示的点点点loading效果: 一:CSS3 animation实现代码 html代码: 提交订单中<span class="ani_dot">...< ...