2012-09-10 8 views
7

Sto provando a creare un controller usando Luaj + java. Ho le seguenti classi JavaCome posso passare oggetti a una funzione luaj esposta?

public class Duck { 
    public void talk() { System.out.println("Duck quacks!"); } 
    public void walk() { System.out.println("Duck walks!"); } 
} 

public class Person { 
    public void talk() { System.out.println("Person talks!"); } 
    public void walk() { System.out.println("Person walks!"); } 
} 

e il seguente script lua per il controllore:

onTalk(obj) 
    obj:talk(); 
end 

onWalk(obj) 
    obj:walk(); 
end 

vorrei idealmente come per definire un controller (scritti in LUA), dove terrò tutto il programma di logica, e vorrei esporre API da quel controller al mio codice java. Stavo cercando di utilizzare il seguente approccio:

ScriptEngineManager sem  = new ScriptEngineManager(); 
ScriptEngine  engine = sem.getEngineByExtension(".lua"); 
ScriptEngineFactory factory = engine.getFactory(); 

// Script defined above 
CompiledScript cs = ((Compilable)engine).compile(MY_LUA_SCRIPT); 
SimpleBindings b = new SimpleBindings(); 

b = newSimpletBindings(); 

LuaValue onWalkHandler = (LuaValue)b.get("onWalk"); 
//func.call(LuaValue.valueOf(duck)); // Passing duck object does not work ??? 

io non sono in grado di passare l'oggetto al LuaValue. Come posso passare un oggetto java allo script lua?

PS: In generale, quando si utilizza Java e script incorporati, le persone raggruppano le funzioni in uno script oppure esiste uno script separato per ogni callback?

risposta

24

Stavo cercando le voci e ho trovato il vostro senza risposta. La tua domanda è stata interessante e mi ha fatto cercare. Poi ho capito che è stato chiesto 2 anni fa ... Spero che la mia risposta possa essere utile a qualcun altro! Codice basato su luaj-3.0-alpha1.

Abbiamo bisogno di uno script Lua valido (hai dimenticato la parola chiave function):

function onTalk(javaObj) 
    print(type(javaObj) .. " " .. tostring(javaObj)) 
    print(javaObj.name) 
    javaObj:talk() 
    return true 
end 

function onWalk(javaObj) 
    javaObj:walk() 
    return 1, "km" 
end 

ho aggiunto un po 'di traccia ... ho anche fatto le classi simili al vostro:

class Dog 
{ 
    public String name; 
    Dog(String n) { name = n; } 
    public void talk() { System.out.println("Dog " + name + " barks!"); } 
    public void walk() { System.out.println("Dog " + name + " walks..."); } 
} 
class Cat 
{ 
    String name; 
    Cat(String n) { name = n; } 
    public void talk() { System.out.println("Cat " + name + " meows!"); } 
    public void walk() { System.out.println("Cat " + name + " walks..."); } 
} 

Aggiungere un campo per testare anche questo. Per la mia prova, ho appena dichiarato le classi all'interno del metodo creando le loro istanze:

Dog dog = new Dog("Rex"); 
Cat cat = new Cat("Felix"); 

primo luogo ho cercato di convertire questi oggetti Java a Lua, utilizzando LuaValue luaDog = LuaValue.userdataOf(dog); ma non funziona: abbiamo infatti abbiamo datiutente, come mostrato per le tracce, ma non per le metatable, quindi non possiamo chiamare i metodi né accedere ai campi.

Dopo aver cercato un sacco, ho trovato la giusta formula magica:

CompiledScript script = ((Compilable) scriptEngine).compile(reader); 
Bindings sb = new SimpleBindings(); 
script.eval(sb); // Put the Lua functions into the sb environment 
LuaValue luaDog = CoerceJavaToLua.coerce(dog); // Java to Lua 
LuaFunction onTalk = (LuaFunction) sb.get("onTalk"); // Get Lua function 
LuaValue b = onTalk.call(luaDog); // Call the function 
System.out.println("onTalk answered: " + b); 
LuaFunction onWalk = (LuaFunction) sb.get("onWalk"); 
LuaValue[] dogs = { luaDog }; 
Varargs dist = onWalk.invoke(LuaValue.varargsOf(dogs)); // Alternative 
System.out.println("onWalk returned: " + dist); 

Apprezzo l'API Luaj ... :-) Probabilmente più fatta per i programmatori Java, mentre altre biblioteche sembrano puntare più a Lua/C programmatori ...

+3

Santo schifo questo è oro. Grazie. – Qix

Problemi correlati