2012-09-10 55 views
7

我想用Luaj + java構建一個控制器。我有以下的Java類如何將對象傳遞給暴露的luaj函數?

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!"); } 
} 

和控制器以下LUA腳本:

onTalk(obj) 
    obj:talk(); 
end 

onWalk(obj) 
    obj:walk(); 
end 

我非常喜歡來定義一個控制器(用LUA),我將保留所有的程序的邏輯,我想將該控制器的API公開給我的java代碼。我試圖使用以下方法:

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 ??? 

我無法將對象傳遞給LuaValue。我如何將java對象傳遞給lua腳本? PS:通常,當使用Java和嵌入式腳本時,人們是否將函數捆綁在一個腳本中,或者每個回調都有單獨的腳本?

回答

24

我正在搜索條目,發現你沒有答案。你的問題很有趣,讓我搜索。然後我意識到這是2年前問的......我希望我的回答對其他人有用!基於luaj-3.0-alpha1的代碼。

我們需要一個有效的Lua腳本(你忘了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 

我平添了幾分痕跡...... 我也做了類似的類到你:

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..."); } 
} 

添加一個字段也可以測試。對於我的測試,我只是宣佈類中的方法創建它們的實例:

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

我第一次嘗試轉換這些Java對象到Lua,使用LuaValue luaDog = LuaValue.userdataOf(dog);但它不工作:我們確實有用戶數據,如圖所示由痕跡,但沒有metatable,所以我們不能調用的方法,也不能訪問字段。

搜索了很多之後,我找到了正確的咒語:

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); 

我很欣賞的Luaj API ... :-)也許更多的Java程序員製成,而其他庫似乎在Lua的瞄準更加/ C程序員...

+3

這是黃金的廢話。謝謝。 – Qix