與 Lua Five 的相容性 |
|
此頁面的主要目標與 [Compat5-1] 相同,但形式是一系列提示,而非一組檔案。
Hisham 製作了一個 [相容性模組,為 Lua 5.1 提供 Lua-5.2 風格的 API]。
參考資料
(括弧中說明變更所針對的 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.0 至 Lua 5.2 的變更很棘手,應手動修正。
table.getn()
的呼叫(Lua 5.0)
table.getn
僅在 Lua 5.0 中定義,較新的版本推薦使用 長度運算子 取代(請參閱 [關於移除 table.getn
的說明])。
如果僅在測試檔中使用 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
參考資料
for
和 repeat
中變數的範圍(Lua 5.0)隱式 for
變數和 repeat
中的區域變數的範圍,在 Lua 5.0 到 Lua 5.1 期間有變更。這必須手動檢查。
參考資料
沒有方法可以寫出與所有 Lua 5.X 版本相容的巢狀長字串。應手動調整程式碼以避免這種結構。
從 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
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.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_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);
Lua 5.2 模組很容易就可以相容於早先的 Lua 5.X 版本,只要提供下列單一函數:luaL_setfuncs
#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);