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() 定义模块
解决方案:

  1. 通过luaconf.h.in中LUA_COMPAT_MODULE宏定义打开兼容支持
  2. 在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 = 1while true dolocal name, val = debug.getupvalue(fn, i)if name == "_ENV" thenreturn valelseif not name thenbreakendi = i + 1end
endlocal function setfenv(fn, env)local i = 1while true dolocal name = debug.getupvalue(fn, i)if name == "_ENV" thendebug.upvaluejoin(fn, i, (function()return envend), 1)breakelseif not name thenbreakendi = i + 1endreturn 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 升级 小结相关推荐

  1. mysql dump工具升级_MySQL数据库升级

    当前不少系统的数据库依旧是MySQL5.6,由于MySQL5.7及MySQL8.0在性能及安全方面有着很大的提升,因此需要升级数据库.本文通过逻辑方式.物理方式原地升级来介绍MySQL5.6 升级至M ...

  2. mysql_upgrade 升级_采用MySQL_upgrade升级授权表方式升级

    [[email protected] MySQL]# /usr/local/MySQL/bin/MySQL_upgrade Looking for 'MySQL' as: bin/MySQL Look ...

  3. linux deepin 20.4升级至20.5教程:升级系统和升级内核两个步骤(手动升级deepin内核命令)

    升级系统版本 在控制中心点击更新就可以实现. 升级内核版本 在控制中心完成系统版本的升级之后,发现内核版本并没有进行同步升级,这时候就需要手动实现内核的升级.手动升级内核的命令如下: sudo apt ...

  4. Android 系统(144)---整包升级与差分升级的区别

    整包升级与差分升级的区别 原文地址:FULL VS INCREMENTAL OTA 一.简介: OTA升级有两种类型,每一种类型都有对应的用途和优势.但是,只有一种类型是用户常常能够接触到的.现在我们 ...

  5. 4-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(远程升级WIFI内部程序)

    https://www.cnblogs.com/yangfengwu/p/10360618.html 演示视频: https://www.bilibili.com/video/av54894356/ ...

  6. ubuntu14.04升级以及gitlab升级

    环境:系统版本ubuntu14.04 .gitlab-ce.8.11.3 升级要求:系统升级为目前最新的LTS版本的ubuntu16.04.gitlab升级为最新的版本 升级可以有两种方案: 一种类似 ...

  7. Oracle 10g升级之--PSU 升级(续)

    Oracle 10g升级之--PSU升级(续) 5.再从10.2.0.4.4 升级到10.2.0.4.11 -----------升级到10.2.0.4.11 [oracle@RH4 12879929 ...

  8. 电信物联网平台SOTA升级(软件升级)的全流程说明

      中国电信物联网开放平台(以下简称"平台")提供了基于LWM2M的固件升级功能,用于模组的固件升级.但是由于多数模组并未提供升级接口给MCU,所以MCU升级只能基于应用层来实现升 ...

  9. rust墙壁升级点什么_明日之后屋子墙壁怎么升级?墙壁升级条件方法一览

    明日之后屋子墙壁怎么升级?墙壁升级条件方法一览 2018-11-05 16:06 作者:佚名 来源:本站整理 浏览:4868 明日之后屋子墙壁怎么升级?在明日之后手游中,我们可以通过一些方法给自己屋子 ...

  10. rust建造一键升级_rust一键升级指令 | 手游网游页游攻略大全

    发布时间:2017-05-29 1.9-1.10一键卧室家具指令 让你的卧室更舒适.那下面则是一个可以帮助玩家更快速的制作家具装饰自己卧室的一键命令方块指令哦~有感兴趣的玩家不妨进来看看下面的介绍吧! ...

最新文章

  1. python 中遍历表时候,当指定的表的长度超过实际长度时候,实际遍历的长度以表实际长度为准,不会发生越界,如下
  2. 餐饮供应链公司“鲜沐农场”获千万级Pre-A轮融资,未来要打造一站式采购平台...
  3. IE6,IE7,FF等浏览器不兼容原因及解决办法(转)
  4. firework常用快捷键
  5. MAT之SA:利用SA算法解决TSP(数据是14个虚拟城市的横纵坐标)问题
  6. selenium(2.4.0)中不能导出web drive 代码
  7. sed是linux命令吗,Linux命令 sed
  8. python numpy教程_Python中的Numpy入门教程
  9. TBXML常用API
  10. java中删除特定后缀名文件
  11. shell如何检测linux发行版本,shell判断软件版本
  12. Unity连接本地数据库sqlite
  13. MOSE:针对配置管理服务器的后渗透工具
  14. UG NX10.0软件安装教程
  15. 镜像翻转_《蒙娜丽莎》镜像翻转后,暗藏神秘的第二张脸?网友:笑容消失了...
  16. 帧率FPS,屏幕刷新频率赫兹Hz
  17. 多维度对抗 Windows AppLocker
  18. 常见的网络品牌营销的方法和渠道
  19. 医疗器械行业数据分析必备软件--全球可查
  20. 嵌入式--轮询调度模块

热门文章

  1. 3.7 Spark RDD编程
  2. New to Machine Learning? Avoid these three mistakes
  3. Pycharm远程调试服务器程序
  4. mysql数据迁移到sqlserver_Oracle,SQL Server,Mysql 三种数据库两表联合更新的方法
  5. 新型消防机器人作文_说一说消防机器人
  6. HarmonyOS 编译系统源码
  7. 搭建Android/Linux驱动编译开发环境篇
  8. rk3399 io工具的使用示例
  9. 103-PHP定义一个类
  10. [Algorithm] Write your own Math.pow function in Javascript, using Recursive approach