与 Lua 五的兼容性

lua-users home
wiki

此页面提供了一些开发者可以采用的提示,以将为 Lua 5.1 编写的代码转换为也与 Lua 5.0 和 Lua 5.2 兼容的代码。

此页面的主要目标与 [Compat5-1] 相同,但形式是一组提示,而不是一组文件。

Hisham 制作了一个 [为 Lua 5.1 提供 Lua-5.2 风格 API 的兼容性模块]

参考资料

(括号中表示更改针对的目标 Lua 版本)

Lua 文件

标准化对 require() 的调用 (Lua 5.0 和 5.1)

重写对 require 的调用以保存其返回值(另请参见下面的“module()”)。例如

require"lib"

变为

local lib = require"lib"

参考资料

删除 module() (Lua 5.1)

可以删除对 module() 的调用,并且代码应该被修改为返回一个包含导出函数的表。有不同的方法可以修改代码。最简单的方法是

local function func1(...) ... end
local function func2(...) ... end

return {
    func1 = func1,
    func2 = func2,
}

某些模块可能需要另一种方法,例如

local _M = {}
function _M.func1(...) ... end
function _M.func2(...) ... end

return _M

参考资料

环境 (Lua 5.1)

从 Lua 5.0 到 Lua 5.2 与环境相关的更改很棘手,应该手动更正。

删除对 table.getn() 的调用 (Lua 5.0)

table.getn 仅在 Lua 5.0 中定义,长度运算符 是在以下版本中推荐的替代方法(参见 [关于 table.getn 弃用的说明])。

如果 table.getn 仅在测试文件中使用,则可以定义

if string.find(_VERSION, " 5.0") then
    table.getn = function (t)
        if t.n then
            return t.n
        else
            local n = 0
            for i in pairs(t) do
                if type(i) == "number" then
                    n = math.max(n, i)
                end
            end
        return n
        end
    end
end

尽管在这种情况下应该考虑为不同版本的 Lua 分发单独的文件。

删除旧的 for 结构 (Lua 5.0)

旧的结构应该很容易转换为与 Lua 5.X 兼容的形式

for i,v in t do ... end

应该重写为

for i,v in pairs(t) do ... end

参考资料

forrepeat 中变量的作用域 (Lua 5.0)

从 Lua 5.0 到 Lua 5.1,隐式 for 变量和 repeat 中的局部变量的作用域发生了变化。这必须手动检查。

参考资料

长字符串的嵌套 (Lua 5.0)

无法编写与所有 Lua 5.X 版本兼容的嵌套长字符串。应手动调整代码以避免这些结构。

C 文件

推送整数(Lua 5.0)

自 Lua 5.1 起,定义了函数 lua_pushinteger。尽管它是一个函数,但以下宏将使 Lua 5.1/5.2 代码向后兼容 Lua 5.0

#if !defined(LUA_VERSION_NUM)
#define lua_pushinteger(L, n) lua_pushnumber(L, (lua_Number)n)
#endif

定义 C 函数列表(Lua 5.0)

luaL_reg(Lua 5.0)自 Lua 5.1 起更名为 luaL_Reg。这可以通过条件编译来解决

#if !defined LUA_VERSION_NUM
/* Lua 5.0 */
#define luaL_Reg luaL_reg
#endif

设置表字段(Lua 5.0)

自 Lua 5.1 起,定义了函数 lua_setfield。因此,可以定义以下宏以使 Lua 5.1/5.2 代码向后兼容 Lua 5.0

#if !defined(LUA_VERSION_NUM)
#define lua_setfield(L, i, k)   (lua_pushstring(L, k), lua_settable(L, i))
#endif

引用(Lua 5.0 和 Lua 5.1)

已弃用的函数 lua_getref()lua_unref() 很容易转换为兼容的调用。例如

/* This code is compatible with previous versions (4.0) */
lua_getref(L, ref);
lua_unref(L, ref);

应该重写为

/* This is Lua 5.X code *;
lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
luaL_unref(L, LUA_REGISTRYINDEX, ref);

注册 C 函数(Lua 5.0 和 5.1)

只要有一个函数:luaL_setfuncs,Lua 5.2 模块就很容易与之前的 Lua 5.X 版本兼容。

#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
/*
** Adapted from Lua 5.2.0
*/
static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
  luaL_checkstack(L, nup+1, "too many upvalues");
  for (; l->name != NULL; l++) {  /* fill the table with given functions */
    int i;
    lua_pushstring(L, l->name);
    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
      lua_pushvalue(L, -(nup+1));
    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
    lua_settable(L, -(nup + 3));
  }
  lua_pop(L, nup);  /* remove upvalues */
}
#endif

此外,应根据其**第二个**参数更改对 luaL_openlib()luaL_register() 的调用。

例如 luaL_openlib(L, NULL, lreg, x); 应改写为 luaL_setfuncs(L, lreg, x);

例如 luaL_openlib(L, name, lreg, x); 应谨慎改写,因为将搜索并可能创建具有给定名称的全局表。

例如 luaL_register(L, NULL, lreg); 应改写为 luaL_setfuncs(L, lreg, 0);

例如 luaL_register(L, name, lreg); 应谨慎改写,因为将搜索并可能创建具有给定名称的全局表。如果可能,应改写为 luaL_setfuncs(L, lreg, 0);


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2014 年 2 月 7 日下午 6:30 GMT (差异)