**
熱更一般是針對模組的線上替換。我們動態載入要熱更的模組試試。例如,我們在迴圈間隔載入某模組,這樣就能有時間去更改模組了。測試的**如下:
for i = 1, 5 do
local m = require('other')
print('other.a is ', m.a)
sleep(5)
end我們迴圈載入了other這個模組他僅僅返回乙個local table ,在sleep(lua沒有直接提供sleep,我們可以利用os模組自己實現)期間我們改變other模組a的值為101,不出意外,m.a還是100。這是為什麼呢?
這是由於require快取機制決定的,請參考lua require機制
要想打破require快取機制,我們必須刪除快取,package.loaded[module_name] = nil就可以做到。
我們將package.loaded['other'] = nil加在第四行後,再改變a的值,不出意外,a的值被改變了。
還有乙個問題就是,之前的舊資料可能被其他變數引用,所以舊資料仍然有可能存在,例如下面的**:
local g = {}
for i = 1, 5 do
local m = require('other')
if (i == 1) then g = m end
print('other.a is ', m.a)
sleep(5)
package.loaded['other'] = nil
end由於g第一次引用的是舊資料,最後列印g.a時還是100,而不是修改之後的值。我們畫個示意圖就能很好的說明問題:
左邊是lua全域性表package.loaded,require模組就會填入其中。再次require時我們發現他已經指向另乙個表了,而g仍然指向之前的表資料。
怎麼才能讓g指向新的表資料,直接讓g指向他不行嗎?不太可行,因為在實際的專案中不太確定有哪些變數引用到了舊的資料,就算知道,那也是侵入式的修改了。另一種方法就是package.loaded仍引用舊的資料表,只不過與新的資料表交換資料。還是畫個示意圖:
有了上面的描述,相信**實現很簡單:
function reload_module(module_name)
local old_module = package.loaded[module_name] or {}
package.loaded[module_name] = nil
require (module_name)
local new_module = package.loaded[module_name]
for k, v in pairs(new_module) do
old_module[k] = v
endpackage.loaded[module_name] = old_module
return old_module
end以上有個問題就是模組返回的最好是表資料,這樣才能替換已經引用到的舊資料,例如g。
還有,如果要熱更的模組中有全域性變數,熱更模組時修改了全域性變數,那麼在_g['other']指向的值也會被覆蓋,這沒什麼問題,本來全域性變數就應該被覆蓋才對。但是在熱更之前如果有變數指向這個全域性變數就糟糕了,這個變數也應該被修改才對。所以類似上面的交換新舊package.loaded['other']資料,全域性資料也應該交換才對。可惜的是,沒有辦法知道全域性變數來自哪個模組,所以無法做到替換該模組的全域性變數。不知道大佬們有沒有辦法。
Lua熱更新原理及示例
網上有不少lua熱更新的文章,都只說了理論,被沒有給出實際可操作的 下面是我寫的幾個例子。lua的require modelname 把乙個lua檔案載入存放到package.loaded modelname 當我們載入乙個模組的時候,會先判斷是否在package.loaded中已存在,若存在則返回...
lua 熱更新模組
最近準備在手機專案客戶端中使用lua,以前一直在伺服器使用luabind.另外,tolua 也體驗過,luaplus也在早年用過.以下是本人對這些繫結庫的個人感覺 luabind 利用boost機制把繫結做到極致,比較適合主c 弱lua的指令碼框架.作者已經停止更新,在windows linux編譯...
使用LUA 熱更新模組
最近準備在手機專案客戶端中使用lua,以前一直在伺服器使用luabind.另外,tolua 也體驗過,luaplus也在早年用過.以下是本人對這些繫結庫的個人感覺 luabind 利用boost機制把繫結做到極致,比較適合主c 弱lua的指令碼框架.作者已經停止更新,在windows linux編譯...