lua源碼解析,解析lua腳本
chanong
簡(jiǎn)介如今,大多數(shù)在Java 中運(yùn)行Lua 腳本的程序都使用Luajava。然而Luajava有一個(gè)嚴(yán)重的問題,它對(duì)字節(jié)數(shù)組和字符串一視同仁,使得反射效率相對(duì)較低。為了彌補(bǔ)這些問題,我引用了luajava,重寫了它的Java和jni代碼,并以mLua的名稱重新發(fā)布。
功能描述與luajava類似。 mLua還包含全局lua函數(shù),Java對(duì)象和lua對(duì)象可以通過(guò)JNI層代碼進(jìn)行交換。但是mLua禁止Lua直接操作Java對(duì)象,所以如果想在Lua中使用Java對(duì)象,就必須使用內(nèi)置的全局函數(shù)。
mLua 區(qū)分字節(jié)數(shù)組和字符串。在mLua 中,Java 字節(jié)數(shù)組只是Lua 端的常規(guī)用戶數(shù)據(jù)。
語(yǔ)言之間的數(shù)據(jù)交換過(guò)程中會(huì)復(fù)制字符串,因此當(dāng)字符串從Lua傳遞到Java并在Lua中修改時(shí),Java端對(duì)應(yīng)的版本保持不變。
Lua端的數(shù)字傳遞給Java后,最初被解釋為字節(jié)類型。否則,它嘗試根據(jù)字節(jié)-短-整數(shù)-長(zhǎng)-浮點(diǎn)-雙鏈進(jìn)行解釋。
mLua 不向外界暴露Lua 解析器實(shí)例;所有操作都是基于MLua 實(shí)例完成的。
Java端方法描述MLua的Java端方法集中在MLua中。
方法名稱方法說(shuō)明setBasedir(String) 設(shè)置lua 代碼的最外層目錄。所有l(wèi)ua代碼都應(yīng)該存放在該目錄或其子目錄中。 PushGlobal(String, Object) 設(shè)置全局lua 全局變量或函數(shù)。您可以推送常規(guī)對(duì)象或JavaFunctions。
后者代表lua函數(shù)的Java實(shí)現(xiàn)。配置數(shù)據(jù)僅在執(zhí)行start方法之前生成。
使用start(String)啟動(dòng)Lua解析器,傳遞的參數(shù)代表Lua代碼入口文件。 Stop() 停止Lua 解析器并釋放資源。
此外,JavaFunction 也是您需要使用的接口。這代表了lua函數(shù)的Java實(shí)現(xiàn)。其回調(diào)方法execute(Object[])傳遞Lua端輸入的數(shù)據(jù),并將結(jié)果輸出到Lua端。如果方法本身不需要返回任何數(shù)據(jù),則返回null即可。
Lua側(cè)函數(shù)描述在mLua下,原有的Lua require和print函數(shù)都被重寫了。
我需要
require必須使用Java端設(shè)置的basedir作為根目錄的相對(duì)路徑來(lái)引用其他lua腳本。
需要“dir1/dir2/script1” 需要“script2”
支持輸出一個(gè)或多個(gè)對(duì)象,但不能組合字符串和Java對(duì)象。
-- 正確的做法--print(\'hello mLua\')print(\'context: \', getContext())print(\'string \' . 111) -- 錯(cuò)誤的做法--print(\' context: \ ' . getContext()) 以逗號(hào)分隔的對(duì)象在Java 端以制表符分隔顯示。
操作Java 對(duì)象
mLua也使用反射來(lái)操作Java對(duì)象,但是mobTools的ReflectHelper具有緩存功能,理論上每次都比luajava直接反射更快。 mLua 提供以下內(nèi)置函數(shù)。
函數(shù)名稱函數(shù)說(shuō)明import(className) 將類導(dǎo)入ReflectHelper 類緩存。這個(gè)函數(shù)是
細(xì)繩。在后續(xù)代碼中用于從緩存中檢索導(dǎo)入的類實(shí)例。 import(name, className) 將類導(dǎo)入ReflectHelper 類緩存并使用此緩存鍵。
構(gòu)造一個(gè)具有指定名稱new(className,) 的Java 實(shí)例。參數(shù)className是導(dǎo)入函數(shù)的返回值。
后續(xù)參數(shù)是Java 構(gòu)造函數(shù)方法invokeStatic(className, methodName,) 的輸入?yún)?shù)。此方法調(diào)用Java 靜態(tài)方法invoke(receiver, methodName,) 和Java 實(shí)例方法getStatic(className, fieldName)。 )獲取Java。靜態(tài)字段setStatic(className, fieldName, value) 設(shè)置java 靜態(tài)字段。 get(receiver, fieldName) 獲取Java 實(shí)例字段。 set(receiver, fieldName, value) 設(shè)置Java 實(shí)例字段。 createProxy(proxyTable, ) 構(gòu)造一個(gè)Java 接口代理。參數(shù)proxyTable是一個(gè)Lua表。
key必須與Java接口類中的方法名相同,key對(duì)應(yīng):
value是一個(gè)Lua函數(shù),函數(shù)的參數(shù)列表和返回值也是
必須與Java接口相同。 proxyTable后面的參數(shù)是實(shí)現(xiàn)的接口
列表名稱(所有字符串)由導(dǎo)入函數(shù)返回。這個(gè)函數(shù)是
Java接口代理實(shí)例。它可以傳遞到Java端并進(jìn)行操作。
mLua在調(diào)用實(shí)例中的接口函數(shù)時(shí)會(huì)調(diào)用proxyTable。
完成功能碼對(duì)應(yīng)的操作
Java 邊代碼示例
public class MainActivity extends Activity { private MLua lua; protected void onCreate(Bundle SavedInstanceState) { super.onCreate(savedInstanceState); //構(gòu)造解析器實(shí)例lua=new MLua(); //設(shè)置Lua代碼的保存位置lua .setBasedir ( \'/sdcard/mLua/LuaTest\'); //推送全局對(duì)象lua.pushGlobal(\'getContext\', new JavaFunction() { public Objectexecute(Object[] args) throws Throwable { return getApplication( ); } }); try { //啟動(dòng)解析器,設(shè)置main.lua為入口代碼lua.start(\'main\'); } catch (Throwable e) { e.printStackTrace(); } } protected void onDestroy() { //關(guān)閉解析器lua.stop(); super.onDestroy(); }}lua 端代碼
-- 導(dǎo)入ReflectHelper.ReflectRunnable 類并將其命名為ReflectRunnable --import(\'ReflectRunnable\', \'com.mob.tools.utils.ReflectHelper$ReflectRunnable\') 本地函數(shù)main() -- 打印并演示call - - print(\'來(lái)自mLua 的hello world\') local context=getContext() print(\'當(dāng)前context: \', context) local packageName=invoke(context, \'getPackageName\') print(\ 'packageName: \ ', packageName) -- Java 接口代理演示-- local luaCode={ run=function(arg) print(\'luaCode.run(), input: \', arg) return \'yoyoyo\' end } local proxy=createProxy (luaCode , \'ReflectRunnable\') local res=invoke(proxy, \'run\', packageName) print(\'luaCode.run(), Output: \', res) -- 復(fù)制數(shù)組演示-- local bArray=new( \'[B\', 16) for i=0, 15 do set(bArray, \'[\' . i . \']\', i + 1) end local bArray2=new(\ '[B \', get(bArray, \'length\')) invokeStatic(\'System\', \'arraycopy\', bArray, 0, bArray2, 0, 16) for i=0, 15 do print( \'bArray2 [\' . i . \']: \', get(bArray2, \'[\' . i . \']\')) endendmain() 擴(kuò)展子mLua只能加載lua通過(guò)以下方式從文件系統(tǒng)中獲。弘m然這是默認(rèn)代碼,但您可以重寫MLua 的setBasedir 方法并以不同的方式實(shí)現(xiàn)SourceLoader,以任何您想要的方式加載Lua 代碼,包括資產(chǎn)和加密代碼。








