2012-09-10 17 views
7

Tôi đang cố gắng xây dựng một bộ điều khiển bằng cách sử dụng Luaj + java. Tôi có các lớp java sauLàm cách nào để chuyển đối tượng sang hàm luaj được phơi sáng?

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

và kịch bản lua sau cho bộ điều khiển:

onTalk(obj) 
    obj:talk(); 
end 

onWalk(obj) 
    obj:walk(); 
end 

Tôi lý tưởng muốn xác định một bộ điều khiển (viết bằng lua), nơi tôi sẽ giữ tất cả các chương trình của logic, và tôi muốn để lộ API từ bộ điều khiển đó đến mã java của tôi. Tôi đã cố gắng sử dụng các phương pháp sau đây:

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

Tôi không thể vượt qua các đối tượng để các LuaValue. Làm thế nào tôi có thể vượt qua một đối tượng java để kịch bản lua?

PS: Nói chung, khi sử dụng Java và tập lệnh nhúng, hãy thực hiện các chức năng của mọi người trong một tập lệnh hoặc có một tập lệnh riêng cho mỗi cuộc gọi lại không?

Trả lời

24

Tôi đã tìm kiếm mục và tìm thấy câu trả lời chưa được trả lời của bạn. Câu hỏi của bạn thú vị và khiến tôi tìm kiếm. Sau đó, tôi nhận ra rằng nó đã được hỏi 2 năm trước ... Tôi hy vọng câu trả lời của tôi có thể hữu ích cho người khác! Mã dựa trên luaj-3.0-alpha1.

Chúng ta cần một kịch bản Lua hợp lệ (bạn quên từ khóa 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 

tôi đã thêm một chút dấu vết ... tôi cũng thực hiện các lớp học tương tự như của bạn:

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

Thêm một trường để kiểm tra điều này. Đối với thử nghiệm của tôi, tôi chỉ công bố các lớp bên trong phương pháp tạo ra các trường hợp của họ:

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

đầu tiên tôi đã cố gắng để chuyển đổi các đối tượng Java Lua, sử dụng LuaValue luaDog = LuaValue.userdataOf(dog); nhưng nó không hoạt động: chúng ta thực sự có userdata, như thể hiện bởi các dấu vết, nhưng không thể so sánh được, vì vậy chúng ta không thể gọi các phương thức cũng như không truy cập các trường.

Sau khi tìm kiếm rất nhiều, tôi phát hiện ra câu thần chú phải:

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

Tôi đánh giá cao các API Luaj ... :-) Có lẽ hơn làm cho các lập trình Java trong khi các thư viện khác dường như nhằm mục đích hơn tại Lua/Lập trình viên C ...

+3

Cái crap thánh này là vàng. Cảm ơn bạn. – Qix