詳解在JAVA(J2ME)中使用Lua腳本引擎kahlua
在JAVA(J2ME)中使用Lua腳本引擎kahlua是本文要介紹的內(nèi)容,主要是來(lái)學(xué)習(xí)JAVS中如何來(lái)使用LUA,Lua有幸被暴雪選中,在魔獸中大量應(yīng)用,從而獲得了極快的發(fā)展,Lua也因此成為游戲、軟件開發(fā)中腳本語(yǔ)言的首選。Lua是一種十分簡(jiǎn)潔的腳本語(yǔ)言,不過(guò)寫起來(lái)并不是很簡(jiǎn)單,當(dāng)然過(guò)分的簡(jiǎn)化使得程序本身有些混亂。具體的語(yǔ)言教程在網(wǎng)上有很多,這里就不再說(shuō)了。
kahlua最初是為J2ME設(shè)計(jì)的,現(xiàn)在已經(jīng)擴(kuò)展到J2SE,項(xiàng)目地址是http://code.google.com/p/kahlua/,在這里可以下載到源代碼及編譯好的jar包。在實(shí)際應(yīng)用中我發(fā)現(xiàn)J2ME中導(dǎo)入jar包很困難,弄了好幾天也沒(méi)有成功,只好將源代碼放在在工程的目錄里一同編譯。kahlua可以識(shí)別*.lua及*.lbc文件,*.lbc是編譯后的lua文件,項(xiàng)目中一般使用這種文件,因?yàn)椴粫?huì)泄露lua文件的內(nèi)容??梢缘絟ttp://www.lua.org上下載一個(gè)lua的運(yùn)行環(huán)境,安裝后會(huì)自動(dòng)添加安裝路徑到系統(tǒng)變量,此時(shí)在cmd中運(yùn)行l(wèi)uac程序就可以編譯腳本,命令是luac -o f.lbc d:\f.lua,詳情看幫助文檔。
我下的kahlua是kahlua-release-20090611.zip源代碼包,解壓后是一個(gè)Ant工程,將src目錄下的內(nèi)容及resource中的stdlib.lua(lbc)文件復(fù)制到J2ME項(xiàng)目中src下。在編程之前首先說(shuō)明一點(diǎn),在程序中指定文件的路徑時(shí)要注意對(duì)應(yīng)工程文件的位置。我的工程的src文件夾對(duì)應(yīng)程序中的根目錄,比如說(shuō)上的/src/stdlib.lua在程序中就是/stdlib.lua。
lua腳本語(yǔ)言中一個(gè)獨(dú)特的數(shù)據(jù)類型就是表,表其實(shí)就是java中的map、哈希表,比如說(shuō)下面一個(gè)表:
- T1 = {} -- 定義一個(gè)空表
- T1[1]=10 --定義表的內(nèi)容
- T1["John"]={Age=27, Gender="Male"}
而每一個(gè)腳本文件實(shí)際上就是一個(gè)大表,每一個(gè)變量、方法都是表的成員,因此腳本的變量默認(rèn)都是全局的,而且也可以定以方法為變量,kahlua正是依據(jù)這個(gè)概念來(lái)的。
1、初始化:
- LuaState state=new LuaState(System.out);
- UserdataArray.register(state);
- OsLib.register(state);
- LuaCompiler.register(state);
se.krka.kahlua.vm.LuaState對(duì)象是kahlua引擎的核心,一切操作都由它來(lái)完成,在生成LuaState對(duì)象后再進(jìn)行一些注冊(cè)。
2、獲取全局表:
- LuaTable table=state.getEnvironment();
- LuaTable有一系列函數(shù)添加、獲取腳本內(nèi)容,最常用的有:
- void rawset(Object key, Object value);//添加內(nèi)容
- Object rawget(Object key);//獲取內(nèi)容
3、加載腳本:
- InputStream is=this.getClass().getResourceAsStream(scriptName);
- //scriptName為腳本文件的路徑
- LuaClosure closure=LuaCompiler.loadis(is , "lua" , table);
- //LoadCompiler為編譯器,loadis為加載輸入流的方法
- //is為輸入流;"lua"為編譯器的名字,好像任意字符串都可以;table為全局表
- //LuaClosure為腳本編譯后的語(yǔ)句。
整個(gè)腳本編譯后相當(dāng)于一個(gè)大的方法,并將其添加到全局表。
4、執(zhí)行腳本:
- sate.call(closure, null);
- LuaState的public Object call(Object fun, Object[] args)
方法是用來(lái)執(zhí)行全局表中的方法,前面說(shuō)到,整個(gè)腳本編譯后是作為一個(gè)方法存入全局表的,因此也可以用這個(gè)方法執(zhí)行腳本。
5、方法:
public Object call(Object fun, Object[] args)中fun為函數(shù)對(duì)象,args為參數(shù)
(1)在Java中調(diào)用Lua方法
- state.call( table.rawget("say") , new String[]{"Hello!"});
即從全局表中取出函數(shù)并執(zhí)行。
(2)在Lua中調(diào)用Java方法
首先生成一個(gè)繼承自JavaFunction接口的類,然后添加到全局表中
JavaFunction只有一個(gè)public abstract int call(LuaCallFrame callFrame, int nArguments)方法,其中callFrame用于獲取輸入?yún)?shù)及指定返回值,nArguments獲取輸入?yún)?shù)數(shù)量。返回值為返回參數(shù)的個(gè)數(shù),因?yàn)閘ua函數(shù)可以有多個(gè)返回值的。
- class JavaFunctionSay implements JavaFunction{
- public int call(LuaCallFrame frame, int arg) {
- String str=BaseLib.rawTostring(frame.get(0));//獲取輸入?yún)?shù)
- say(str);//執(zhí)行對(duì)應(yīng)Java內(nèi)容
- frame.push("result");//返回參數(shù)
- return 1;
- }
- }
再用table.rawset("say", new JavaFunctionSay());添加到全局表,這樣就可以在對(duì)應(yīng)Lua腳本中使用say方法了。
附注:
kahlua顯示中文有問(wèn)題,應(yīng)該是編碼不正確,修改LexState中String newstring( byte[] chars, int offset, int len )方法的第一行編碼為"GBK"后好像就可以了。
本人在windows中使用用luac生成的lbc時(shí)出錯(cuò)..文件不支持中文,有中文就會(huì)報(bào)錯(cuò),而英文就能順利通過(guò),想來(lái)可能和字符編碼有關(guān)系...想在lbc中使用中文,本人的方法是:
- File luascript = new File("E:\\getWeather.lua");//--其實(shí)什么后綴名無(wú)所謂的
- File lbcscript=new File("C:\\Users\\信豐boy\\getWeather.lbc");
- closure = LuaCompiler.loadis(new FileInputStream(luascript), "信豐boy",table);//"信豐boy"這個(gè)字符串是可以隨意的.其作用是表示作用域.
- OutputStream os=new FileOutputStream(lbcscript);
- closure.prototype.dump(os);//這樣就把lbc格式的字節(jié)碼文件寫到"C:\\Users\\信豐boy\\getWeather.lbc"了.
- os.close();
當(dāng)下次要調(diào)用的時(shí)候
- File lbcscript=new File("C:\\Users\\信豐boy\\getWeather.lbc");
- closure = LuaPrototype.loadByteCode(new FileInputStream(lbcscript), table);
ps:kuhlua不支持gfind函數(shù),所有你得用find函數(shù)ps:kuhlua不支持gfind函數(shù),所有你得用find函數(shù)。
小結(jié):詳解在JAVA(J2ME)中使用Lua腳本引擎kahlua的內(nèi)容介紹完了,希望通過(guò)本文的學(xué)習(xí)能對(duì)你有所幫助!