如何在Java应用程序中在Android上运行Lua脚本?
我正在用Java开发一个Android游戏,它使用Lua脚本。为了执行这些脚本,我将LuaJ与Java的ScriptEngine类一起使用。例如如何在Java应用程序中在Android上运行Lua脚本?,java,android,lua,Java,Android,Lua,我正在用Java开发一个Android游戏,它使用Lua脚本。为了执行这些脚本,我将LuaJ与Java的ScriptEngine类一起使用。例如 ScriptEngineManager sem = new ScriptEngineManager(); scriptEngine = sem.getEngineByExtension(".lua"); script = ((Compilable)scriptEngine).compile("some lua here"); 然而,Android显然
ScriptEngineManager sem = new ScriptEngineManager();
scriptEngine = sem.getEngineByExtension(".lua");
script = ((Compilable)scriptEngine).compile("some lua here");
然而,Android显然不支持这一点(我在别处读到,这与Android没有成熟的JVM有关)。有没有办法在Android上使用Lua脚本?也许有另一种选择?也许有一种直接使用LuaJ编译和执行Lua脚本的方法(尽管我不知道如何)
仅供参考,当我尝试在Android上运行此代码时,我看到此错误:
05-06 16:12:32.870: E/dalvikvm(17509): Could not find class 'javax.script.ScriptEngineManager', referenced from method unearth.levels.LevelReader.<init>
05-06 16:12:32.870: W/dalvikvm(17509): VFY: unable to resolve new-instance 787 (Ljavax/script/ScriptEngineManager;) in Lunearth/levels/LevelReader;
05-06 16:12:32.870: D/dalvikvm(17509): VFY: replacing opcode 0x22 at 0x0018
05-06 16:12:32.875: E/dalvikvm(17509): Could not find class 'javax.script.Compilable', referenced from method unearth.levels.LevelReader.parseScript
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve check-cast 782 (Ljavax/script/Compilable;) in Lunearth/levels/LevelReader;
05-06 16:12:32.875: D/dalvikvm(17509): VFY: replacing opcode 0x1f at 0x0047
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to resolve exception class 788 (Ljavax/script/ScriptException;)
05-06 16:12:32.875: W/dalvikvm(17509): VFY: unable to find exception handler at addr 0x51
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejecting opcode 0x0d at 0x0051
05-06 16:12:32.875: W/dalvikvm(17509): VFY: rejected Lunearth/levels/LevelReader;.parseScript (Lorg/w3c/dom/Element;Lunearth/levels/Level;)V
05-06 16:12:32.875: W/dalvikvm(17509): Verifier rejected class Lunearth/levels/LevelReader;
05-06 16:12:32.890: W/dalvikvm(17509): threadid=11: thread exiting with uncaught exception (group=0x40c331f8)
05-06 16:12:32.895: E/AndroidRuntime(17509): FATAL EXCEPTION: GLThread 1062
05-06 16:12:32.895: E/AndroidRuntime(17509): java.lang.VerifyError: unearth/levels/LevelReader
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.Game.startGame(Game.java:201)
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.Game.update(Game.java:713)
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.screens.LoadScreen.update(LoadScreen.java:56)
05-06 16:12:32.895: E/AndroidRuntime(17509): at unearth.UnearthListener.render(UnearthListener.java:71)
05-06 16:12:32.895: E/AndroidRuntime(17509): at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:423)
05-06 16:12:32.895: E/AndroidRuntime(17509): at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1462)
05-06 16:12:32.895: E/AndroidRuntime(17509): at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)
05-06 16:12:58.600: D/dalvikvm(17509): GC_CONCURRENT freed 334K, 3% free 16196K/16647K, paused 2ms+6ms
05-06 16:12:32.870:E/dalvikvm(17509):找不到从方法unearth.levels.LevelReader引用的类“javax.script.ScriptEngineManager”。
05-06 16:12:32.870:W/dalvikvm(17509):VFY:无法解析lunerth/levels/LevelReader中的新实例787(Ljavax/script/ScriptEngineManager;);
05-06 16:12:32.870:D/dalvikvm(17509):VFY:在0x0018处替换操作码0x22
05-06 16:12:32.875:E/dalvikvm(17509):找不到从方法unearth.levels.LevelReader.parseScript引用的类“javax.script.Compileable”
05-06 16:12:32.875:W/dalvikvm(17509):VFY:无法解析lunerth/levels/LevelReader中的check cast 782(Ljavax/script/compileable;);
05-06 16:12:32.875:D/dalvikvm(17509):VFY:在0x0047处替换操作码0x1f
05-06 16:12:32.875:W/dalvikvm(17509):VFY:无法解析异常类788(Ljavax/script/ScriptException;)
05-06 16:12:32.875:W/dalvikvm(17509):VFY:无法在地址0x51处找到异常处理程序
05-06 16:12:32.875:W/dalvikvm(17509):VFY:被拒绝的lunerth/levels/LevelReader;。parseScript(Lorg/w3c/dom/Element;lunerth/levels/Level;)V
05-06 16:12:32.875:W/dalvikvm(17509):VFY:在0x0051处拒绝操作码0x0d
05-06 16:12:32.875:W/dalvikvm(17509):VFY:被拒绝的lunerth/levels/LevelReader;。parseScript(Lorg/w3c/dom/Element;lunerth/levels/Level;)V
05-06 16:12:32.875:W/dalvikvm(17509):验证者拒绝等级/等级/等级读取器;
05-06 16:12:32.890:W/dalvikvm(17509):threadid=11:线程以未捕获异常退出(组=0x40c331f8)
05-06 16:12:32.895:E/AndroidRuntime(17509):致命异常:GLThread 1062
05-06 16:12:32.895:E/AndroidRuntime(17509):java.lang.VerifyError:unearth/levels/LevelReader
05-06 16:12:32.895:E/AndroidRuntime(17509):在unearth.Game.startGame(Game.java:201)
05-06 16:12:32.895:E/AndroidRuntime(17509):在unearth.Game.update(Game.java:713)
05-06 16:12:32.895:E/AndroidRuntime(17509):在unearth.screens.LoadScreen.update(LoadScreen.java:56)
05-06 16:12:32.895:E/AndroidRuntime(17509):在unearth.UnearthListener.render(UnearthListener.java:71)
05-06 16:12:32.895:E/AndroidRuntime(17509):位于com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:423)
05-06 16:12:32.895:E/AndroidRuntime(17509):在android.opengl.GLSurfaceView$GLThread.guarderun(GLSurfaceView.java:1462)
05-06 16:12:32.895:E/AndroidRuntime(17509):在android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1216)
05-06 16:12:58.600:D/dalvikvm(17509):GC_并发释放334K,3%释放16196K/16647K,暂停2ms+6ms
更新:
也许这个项目有一些有用的代码
然而,Android显然不支持这一点
对
我在某个地方读到,android没有成熟的JVM
对。如果您查看,您将看到,javax.script
在Android SDK中不存在
也许我会尝试一下:
这是一种选择。另一种方法是通过NDK将Lua解释器嵌入到应用程序中,如中所示。您可以(也)使用LuaJava与使用NDK为Android编译的Lua一起使用。这允许Lua完全访问Java提供的任何内容。看一看,看看如何开始
如果您不想摆弄NDK,Lua5.1.4+LuaJava编译版将在
libs
目录(一个libluajava.so
文件)中提供,但无论如何设置起来都相对容易。我找到了在Android上使用LuaJ的方法:-)
关键是直接使用LuaJ API,而不是通过javax.script
。因为没有教程,所以要弄清楚这一点有点棘手,所以这里有一个前后对比,这样其他人就不必仔细阅读LuaJ源代码和JavaDoc了。我真的希望这能帮助别人,因为它让我发疯
注意:“secretgame”不是我游戏的实际名称;-)
之后:
package secretgame.scripting;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.luaj.vm2.LuaClosure;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Prototype;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.lib.jse.JsePlatform;
import secretgame.SecretGameException;
import secretgame.events.EventArgs;
import secretgame.levels.Level;
public class DirectLuaj implements Lua
{
private final Level level;
private final ScriptTools scriptTools;
private final ScriptEvents scriptEvents;
private int nextId = 0;
private ArrayList<LuaClosure> scripts = new ArrayList<LuaClosure>();
public DirectLuaj(Level level, ScriptTools scriptTools,
ScriptEvents scriptEvents)
{
this.level = level;
this.scriptTools = scriptTools;
this.scriptEvents = scriptEvents;
}
@Override
public int add(String scriptText) throws SecretGameException
{
try {
InputStream input = new ByteArrayInputStream(scriptText.getBytes());
Prototype p = LuaC.compile(input, "script");
LuaValue g = JsePlatform.standardGlobals();
LuaClosure c = new LuaClosure(p, g);
scripts.add(c);
}
catch (IOException e) {
throw new SecretGameException("compile failed", e);
}
return nextId++;
}
@Override
public void run(int id, EventArgs args) throws SecretGameException
{
LuaClosure script = scripts.get(id);
LuaTable bindings = new LuaTable();
bindings.set("java", toLua(scriptTools));
bindings.set("level", toLua(level));
bindings.set("args", toLua(args));
bindings.set("events", toLua(scriptEvents));
script.setfenv(bindings);
script.call();
}
private LuaValue toLua(Object javaValue) {
return javaValue == null? LuaValue.NIL:
javaValue instanceof LuaValue? (LuaValue) javaValue:
CoerceJavaToLua.coerce(javaValue);
}
}
package secretgame.scripting;
import java.util.ArrayList;
import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import secretgame.SecretGameException;
import secretgame.events.EventArgs;
import secretgame.levels.Level;
// sadly this won't work on Android because there's no such thing
// as javax.script in Dalvik ... dumb Android java :|
public class JavaxScriptingLua implements Lua
{
private ScriptEngine scriptEngine;
private final Level level;
private final ScriptTools scriptTools;
private final ScriptEvents scriptEvents;
private int nextId = 0;
private ArrayList<CompiledScript> scripts = new ArrayList<CompiledScript>();
public JavaxScriptingLua(Level level, ScriptTools scriptTools, ScriptEvents scriptEvents)
{
this.level = level;
this.scriptTools = scriptTools;
this.scriptEvents = scriptEvents;
ScriptEngineManager sem = new ScriptEngineManager();
scriptEngine = sem.getEngineByExtension(".lua");
}
public int add(String scriptText) throws SecretGameException
{
try {
CompiledScript script = ((Compilable)scriptEngine).compile(scriptText);
scripts.add(script);
}
catch (ScriptException e) {
throw new SecretGameException("could not compile lua.", e);
}
return nextId++;
}
public void run(int id, EventArgs args) throws SecretGameException
{
Bindings bindings = scriptEngine.createBindings();
bindings.put("java", scriptTools);
bindings.put("level", level);
bindings.put("args", args);
bindings.put("events", scriptEvents);
try {
scripts.get(id).eval(bindings);
}
catch (ScriptException e) {
throw new SecretGameException("could not run script.", e);
}
}
}
package secretgame.scripting;
导入java.io.ByteArrayInputStream;
导入java.io.IOException;
导入java.io.InputStream;
导入java.util.ArrayList;
导入org.luaj.vm2.LuaClosure;
导入org.luaj.vm2.LuaTable;
导入org.luaj.vm2.LuaValue;
导入org.luaj.vm2.Prototype;
导入org.luaj.vm2.compiler.LuaC;
导入org.luaj.vm2.lib.jse.compressejavatola;
导入org.luaj.vm2.lib.jse.jsepplatform;
导入secretgame.SecretGameException;
导入secretgame.events.EventArgs;
导入secretgame.levels.Level;
公共类DirectLuaj实现Lua
{
私人最终级别;
私有最终脚本工具脚本工具;
私人最终ScriptEvents ScriptEvents;
私有int nextId=0;
私有ArrayList脚本=新建ArrayList();
public DirectLuaj(级别、脚本工具、脚本工具、,
ScriptEvents(脚本事件)
{
这个水平=水平;
this.scriptTools=scriptTools;
this.scriptEvents=scriptEvents;
}
@凌驾
public int add(字符串scriptText)引发SecretGameException
{
试一试{
InputStream input=new ByteArrayInputStream(scriptText.getBytes());
Prototype p=LuaC.compile(输入“脚本”);
LuaValue g=jsepplatform.standardGlobals();
LuaClosure c=新LuaClosure(p,g);
添加(c);
}
捕获(IOE异常){
抛出新的SecretGameException(“编译失败”,e);
}
返回nextId++;
}
@凌驾
public void run(int id,EventArgs args)抛出secretgamex