Как я могу передать объекты в открытую функцию luaj?
Я пытаюсь построить контроллер, используя Luaj + Java. У меня есть следующие классы Java
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 и встроенных сценариев люди объединяют функции в один сценарий, или существует отдельный сценарий для каждого обратного вызова?
1 ответ
Я искал записи luaj и нашел ваш без ответа. Ваш вопрос был интересным и заставил меня искать. Тогда я понял, что это было задано 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);
но это не работает: у нас действительно есть пользовательские данные, как показано трассировкой, но нет метатабельных, поэтому мы не можем ни вызывать методы, ни получать доступ к полям.
После долгих поисков я нашел правильное заклинание:
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);
Я ценю API Luaj...:-) Возможно, больше сделано для программистов на Java, в то время как другие библиотеки, похоже, больше нацелены на программистов на Lua / C...