lua(wiki 中文 官方社區:lua-users)是一門開源、簡明、可擴展且高效的弱類型解釋型腳本語言。
由於其實現遵循C標准,它幾乎能在所有的平台(windows、linux、OS X、Android、iOS、PlayStation、XBox、wii等)上運行。
當前最新的lua版本為5.3.5;前兩位版本號為lua的大版本,相同的大版本之間是兼容的;即5.3.5向下兼容5.3.4~0等版本
版本信息定義在lua.h中,即宏LUA_RELEASE
#define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "3" #define LUA_VERSION_NUM 503 #define LUA_VERSION_RELEASE "4" #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE #define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2017 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
lua非常小巧精簡,其解釋器加上周邊的庫函數也不過1w多行代碼。以下是Lua5.3.5的源文件:
核心文件:
文件名 | 作用 | 對外接口前綴 |
lapi.c | c語言接口 | lua_ |
lcode.c | 源碼生成器 | luaK_ |
ldebug.c | 調試庫 | luaG_ |
ldo.c | 函數調用及棧管理 | luaD_ |
ldump.c | 序列化預編譯的lua字節碼 | |
lfunc.c | 提供操作函數原型及閉包的輔助函數 | luaF_ |
lgc.c | GC | luaC_ |
llex.c | 詞法分析 | luaX_ |
lmem.c | 內存管理 | luaM_ |
lobject.c | 對象管理 | luaO_ |
lopcodes.c | 字節碼操作 | luaP_ |
lparser.c | 語法分析 | luaY_ |
lstate.c | 全局狀態機 | luaE_ |
lstring.c | 字符串操作 | luaS_ |
ltable.c | 表操作 | luaH_ |
ltm.c | tag方法 | luaT_ |
lundump.c | 加載預編譯字節碼 | luaU_ |
lvm.c | 虛擬機 | luaV_ |
lzio.c | 緩存流接口 | luaZ_ |
內嵌庫文件:
文件名 | 作用 |
lauxlib.c | 庫編寫時需要用到的輔助函數庫 |
lbaselib.c | 基礎庫 |
lbitlib.c | bit位操作庫 |
lcorolib.c | 協程庫 |
lctype.c | 封裝c標准庫中的ctype文件 |
ldblib.c | 調試庫 |
linit.c | 負責內嵌庫的初始化 |
liolib.c | IO庫 |
lmathlib.c | 數學庫 |
loadlib.c | 動態擴展庫加載器 |
loslib.c | OS庫 |
lstrlib.c | 字符串操作庫 |
ltablib.c | 表操作庫 |
lutf8lib.c | utf8庫 |
解釋器、編譯器文件:
文件名 | 作用 |
lua.c | 解釋器 |
luac.c | 編譯器 |
lua很容易編譯成靜態庫、動態庫或以源代碼的形式集成到應用程序中,並方便地與c/c++及其他語言進行互操作,因此其被稱為膠水語言(glue language)。
如果不想自己編譯lua,可從LuaBinaries下載編譯好的各個平台上靜態庫、動態庫及基於這些庫實現的lua、wlua解釋器、luac編譯器等工具.。
由於其動態性,支持熱更,上手難度低等特點,在游戲行業常常被用來開發業務邏輯。
可使用跨平台vsCode來編輯和調試lua腳本(注:調試需要安裝actboy168的LuaDebug插件 其github在這里,可在vscode的Extensions面板中搜索lua找到它然后直接安裝)。
騰訊也提供了一款vsCode的lua調試器插件:LuaPanda 其github在這里
lua/wlua解釋器
lua.exe、wlua.exe解釋器都可以通過傳入lua文件,來執行lua腳本 如:lua.exe/wlua.exe D:/LuaTest/test1.lua // 將Hello World!字符串打印到控制台和寫入到e:/test.txt文件中
D:/LuaTest/test1.lua內容如下:
print("Hello World!") file = io.open("e:/test.txt", "w") file:write("Hello World!", "\n") file:close()
lua.exe是subsystem:console類型程序,可在控制台交互式地接受用戶的輸入,並能使用print等函數將結果輸出到控制台中
wlua.exe是subsystem:windows類型程序,無控制台窗口,因此不能將結果輸出到控制台中,但可輸出到文件;另外通過加載GUI dll插件模塊,可使用模塊中的接口來創建窗口程序
在lua5.1.5及之前版本,luaforwindows(googlecode上的站點)項目會集成lua在windows上的各個插件,方便大家在windows上使用lua,如今該項目已停更
如:在luaforwindows中就集成了alien插件,該插件中提供的lua版的windows api,配合wlua.exe來運行以下腳本
require "alien" local MessageBox = alien.User32.MessageBoxA MessageBox:types{ret = "long", abi = "stdcall", "long", "string", "string", "long" } MessageBox(0, "Hello World!", "My Window Title", 0x00000040)
lua.exe命令行
lua.exe --help // 查看lua.exe的用法
lua.exe -v // 顯示出Lua版本號 Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
lua.exe // 進入交互模式 windows系統按Ctrl+C、linux系統按Ctrl+D可退出交互模式
lua.exe - // 從標准設備讀入腳本,輸完后按回車,然后按Ctrl+Z並回車,會執行輸入內容 注:進入輸入模式后可按Ctrl+C強制退出
lua.exe e:\Lua\Test.lua // 加載並執行e:\Lua\Test.lua
lua.exe -e "print(type(100))" // 通過-e參數執行一段lua代碼
注:對於5.3版本的Lua,lua.exe在開始執行前,會讀取環境變量LUA_INIT_5_3的值,若其沒定義,則會嘗試另外一個環境變量LUA_INIT;
若該值不以@開頭,會將其作為一段lua代碼進行執行;若以@開頭,則將其作為lua文件路徑載入並執行
lua.exe -e "myPrint=print" e:\Lua\Test.lua 100 200
e:\Lua\Test.lua中的內容如下:
myPrint("Hello") -- 打印所有傳入的命令行參數 for i, v in pairs(arg) do myPrint(i, v) end
輸出結果為:
在運行以前,Lua使用所有參數構造arg表。腳本名e:\Lua\Test.lua索引為0,腳本的參數從1開始增加,腳本前面的參數從-1開始減少
lua.exe -e "myPrint=print" e:\Lua\Test2.lua 1 "hello" true
e:\Lua\Test2.lua中的內容如下:
local a, b, c, d = ... myPrint(a) -- 1 myPrint(b) -- hello myPrint(c) -- true myPrint(d) -- nil
lua.exe -i e:\Lua\Test3.lua // 執行e:\Lua\Test3.lua腳本后,進入交互模式
lua.exe -lmisc.Test4 // 搜索misc.Test4模塊,找到后加載並執行模塊
lua.exe -e "print(package.path);print(package.cpath)" -l misc.Test4 // 打印出lua模塊和c模塊的搜索路徑,按照這些路徑來搜索misc.Test4模塊,找到后加載並執行模塊
E:\Lua\lua\?.lua;E:\Lua\lua\?\init.lua;E:\Lua\?.lua;E:\Lua\?\init.lua;E:\Lua\..\share\lua\5.3\?.lua;E:\Lua\..\share\lua\5.3\?\init.lua;.\?.lua;.\?\init.lua // 將?替換為misc\Test4來搜索lua模塊
E:\Lua\?.dll;E:\Lua\..\lib\lua\5.3\?.dll;E:\Lua\loadall.dll;.\?.dll;E:\Lua\?53.dll;.\?53.dll // 將?替換為misc\Test4來搜索c模塊
注1:對於5.3版本的Lua,package.path會被設置成環境變量LUA_PATH_5_3的值,若其沒定義,則會嘗試另外一個環境變量LUA_PATH;若都沒定義,則使用編譯時定義的默認路徑(如上)
注2:對於5.3版本的Lua,package.cpath會被設置成環境變量LUA_CPATH_5_3的值,若其沒定義,則會嘗試另外一個環境變量LUA_CPATH;若都沒定義,則使用編譯時定義的默認路徑(如上)
注3:在使用環境變量時,可以添加;;來帶上默認路徑;如:將LUA_PATH定義為c:\public;; package.path則會變成c:\public和默認路徑(如上)的集合
注4:若命令行帶上-E參數,則會在阻止使用環境變量,強制使用默認路徑(如上)
Lua C#解釋器
Lua Interpreter使用C#實現的解釋器,它允許使用C#模塊,並能在lua代碼中調用這些C#模塊中的函數
Lua JIT
LuaJIT是(wiki)一款支持JIT的Lua代碼解釋器,使用C語言編寫,已開源(git);當前發布的穩定版本為2.0.5,最新的版本為2.1.0-beta3,只兼容Lua的5.1版本
編譯技術大約分為兩種,一種AOT,將源代碼、中間碼等提前靜態地編譯成本地機器碼,目標用戶直接用本地機器碼的程序來運行
另一種是JIT(Just In Time,即時編譯),一個JIT引擎要想快,它會通過搜集runtime信息,識別出程序的熱點(2/8原則),會將這部分代碼編譯成本地機器碼並緩存起來,以便下一次直接運行;
而對於只執行一次或少量次數的代碼,JIT編譯帶來的執行速度的提升也未必能抵消掉其編譯帶來的時間開銷,這部分代碼JIT引擎會仍然選擇解釋的方式執行
從官網上下載源碼解壓后,在Visual Studio 2008 Command Prompt命令行中,切換當前路徑到<LuaJIT>\src,然后執行msvcbuild.bat
在src目錄中,會得到生成出luajit.exe及依賴文件
要編譯得到64位的luajit,則需要在Visual Studio 2008 x64 Win64 Command Prompt命令行中編譯
如果想調試運行luajit.exe,可按照如下步驟來
① 在msvcbuild.bat腳本搜索/O2,將/O2改為/Od
② 執行msvcbuild.bat debug來生成luajit.exe
③ 用visual studio建立一個命令行工程,如:luajitcmd
④ 把<LuaJIT>\src下所有.h和.c代碼加入工程
⑤ 把工程的調試路徑設置為
命令:$(ProjectDir)..\..\src\luajit.exe
工作目錄:$(ProjectDir)..\..\src\
⑥ 此時就可以正常按f5下斷點調試了
luajit的命令行參數用法與lua.exe/wlua.exe是一致的,只是在其基礎上增加了幾個命令行參數(詳見:這里),可通過luajit.exe --help查看詳細用法
luajit.exe -b Hello.lua Hello.luajit // 將Hello.lua代碼編譯成luajit字節碼(缺省是開啟O3最高優化)
luajit.exe -O0 Hello.lua // 關閉優化,執行Hello.lua代碼
luajit.exe -joff Hello.lua // 關閉jit,僅僅使用解釋器執行Hello.lua代碼
關於luajit字節碼的詳細格式詳見:【技術分享】Lua程序逆向之Luajit文件格式
更多請閱讀:
lua反編譯工具
工具名稱 | 下載地址 | 說明 |
Unluac | java語言實現,lua反編譯器開源項目,可將lua字節碼反編譯為lua代碼 | |
Luadec | c語言實現,結合lua引擎源碼寫的開源lua反編譯器,解析整個lua字節碼文件並盡可能的還原為源碼 | |
Chunkspy | lua語言實現,將lua字節碼翻譯成lua匯編 該工具還包括了一個交互式的命令,可以將輸入的lua腳本轉換成lua字節碼匯編,這對學習lua字節碼非常有幫助 Luadec工具中集成了Chunkspy |
|
luajit-decomp | https://github.com/bobsayshilol/luajit-decomp | au3語言實現,先通過luajit原生的exe文件將luajit字節碼文件轉換成匯編,然后使用該工具將luajit匯編轉換成lua代碼 |
ljd | https://github.com/NightNord/ljd | python語言實現,一款luajit反編譯工具 |
lua性能分析工具
工具名稱 | 下載地址 | 說明 |
pLua | https://github.com/esrrhs/pLua | lua函數熱點分析 |
lua-snapshot | lua內存泄漏 | |
lua_memleak | https://github.com/radiotail/lua_memleak | lua內存泄漏 |
游戲引擎lua插件
插件名稱 | 支持引擎 | 下載地址 | 說明 |
xlua | unity | https://github.com/Tencent/xLua | G6 |
unlua | ue4 | https://github.com/Tencent/UnLua | G6 |
slua | unity | https://github.com/pangweiwei/slua | 潘多拉(Pandora) |
sluaunreal | ue4 | https://github.com/Tencent/sluaunreal | 潘多拉(Pandora) |
ulua | unity | https://github.com/jarjin/uLua | |
tolua | unity | https://github.com/topameng/tolua | |
unreal.lua | ue4 | https://github.com/asqbtcupid/unreal.lua | tianle |
常用庫的lua版本
插件名稱 | 下載地址 | 說明 |
pb的lua化方案1 protoc-gen-lua
|
https://github.com/memoryoff/protoc-gen-lua-bin-fix |
需將proto生成lua代碼 protoc-gen-lua很久沒維護了 protoc-gen-lua-bin適配了lua53版本,並對其做了一些修正 protoc-gen-lua-bin-fix對protoc-gen-lua-bin做了一點修正 支持int64類型補丁:int64 encoder _VarintSize error! |
pb的lua化方案2 pbc |
不需要將proto生成lua代碼 提供c函數來序列化和反序列化pb字節流 |
|
pb的lua化方案3 lua-protobuf |
||
luasocket |
LuaSocket 是 Lua 的網絡模塊,提供了對 TCP、UDP、DNS、HTTP 等多種網絡協議的訪問操作, 包括了兩部分:①使用 C 編寫的針對 TCP 和 UDP 傳輸層的訪問;②用 Lua 編寫,負責應用功能的網絡接口處理。 |