From eb67bd11d0ae599a706f2cbca54e8640f1fbcfe3 Mon Sep 17 00:00:00 2001 From: gudzpoz Date: Thu, 23 May 2024 21:21:25 +0800 Subject: [PATCH] Add LuaFunction interface - Also fix AndroidScriptTest --- .../iroiro/luajava/AndroidScriptTest.java | 5 +-- .../party/iroiro/luajava/LuaTestSuite.java | 8 ++-- .../party/iroiro/luajava/AbstractLua.java | 40 ++++++++++++++++++- .../main/java/party/iroiro/luajava/Lua.java | 16 ++++++++ .../iroiro/luajava/value/LuaFunction.java | 22 ++++++++++ .../party/iroiro/luajava/value/LuaThread.java | 3 +- 6 files changed, 85 insertions(+), 9 deletions(-) create mode 100644 luajava/src/main/java/party/iroiro/luajava/value/LuaFunction.java diff --git a/android/android-test/src/androidTest/java/party/iroiro/luajava/AndroidScriptTest.java b/android/android-test/src/androidTest/java/party/iroiro/luajava/AndroidScriptTest.java index 55aa03b3..ccf8822a 100644 --- a/android/android-test/src/androidTest/java/party/iroiro/luajava/AndroidScriptTest.java +++ b/android/android-test/src/androidTest/java/party/iroiro/luajava/AndroidScriptTest.java @@ -1,6 +1,5 @@ package party.iroiro.luajava; -import android.util.Log; import org.junit.Test; import party.iroiro.luajava.lua51.Lua51; import party.iroiro.luajava.lua52.Lua52; @@ -40,7 +39,7 @@ public void lua54Test() { @Test public void luaJitTest() { try (LuaJit L = new LuaJit()) { - new LuaScriptSuite<>(L, s -> Log.i("test", s)).test(); + new LuaScriptSuite<>(L).test(); } } @@ -48,7 +47,7 @@ public void luaJitTest() { public void luaJTest() { org.junit.Assume.assumeTrue(android.os.Build.VERSION.SDK_INT >= 30); try (AbstractLua L = AndroidLuaTest.getLuaJ()) { - new LuaScriptSuite<>(L, s -> Log.i("test", s)).test(); + new LuaScriptSuite<>(L).test(); } } diff --git a/example/suite/src/main/java/party/iroiro/luajava/LuaTestSuite.java b/example/suite/src/main/java/party/iroiro/luajava/LuaTestSuite.java index cb5a92e4..f5a3a205 100644 --- a/example/suite/src/main/java/party/iroiro/luajava/LuaTestSuite.java +++ b/example/suite/src/main/java/party/iroiro/luajava/LuaTestSuite.java @@ -542,12 +542,14 @@ private void testProxy() { private void testOthers() { L.openLibrary("math"); L.run("assert(1.0 == math.abs(-1.0))"); - - L.register("testOthersFunction", l -> { + L.push(l -> { l.push("Hello"); return 1; }); - L.run("assert('Hello' == testOthersFunction())"); + L.setGlobal("testOthersFunction1"); + L.register("testOthersFunction2", (l, args) -> new LuaValue[]{ l.from("Hello") }); + L.run("assert('Hello' == testOthersFunction1())"); + L.run("assert('Hello' == testOthersFunction2())"); L.newRegisteredMetatable("myusertype"); L.push(l -> { diff --git a/luajava/src/main/java/party/iroiro/luajava/AbstractLua.java b/luajava/src/main/java/party/iroiro/luajava/AbstractLua.java index 98f9a032..7a76979e 100644 --- a/luajava/src/main/java/party/iroiro/luajava/AbstractLua.java +++ b/luajava/src/main/java/party/iroiro/luajava/AbstractLua.java @@ -126,6 +126,9 @@ public void push(@Nullable Object object, Conversion degree) { } else if (object instanceof LuaValue) { LuaValue value = (LuaValue) object; value.push(this); + } else if (object instanceof LuaFunction) { + LuaFunction function = (LuaFunction) object; + this.push(function); } else if (degree == Conversion.NONE) { pushJavaObjectOrArray(object); } else { @@ -244,6 +247,18 @@ public void push(@NotNull JFunction function) { C.luaJ_pushfunction(L, function); } + @Override + public void push(@NotNull LuaValue value) { + checkStack(1); + value.push(this); + } + + @Override + public void push(@NotNull LuaFunction function) { + checkStack(1); + push(new LuaFunctionWrapper(function)); + } + @Override public void pushJavaObject(@NotNull Object object) throws IllegalArgumentException { if (object.getClass().isArray()) { @@ -825,7 +840,7 @@ public Object createProxy(Class[] interfaces, Conversion degree) } @Override - public void register(String name, JFunction function) { + public void register(String name, LuaFunction function) { push(function); setGlobal(name); } @@ -1144,4 +1159,27 @@ private void recycleReferences() { protected boolean shouldSynchronize() { return true; } + + private static class LuaFunctionWrapper implements JFunction { + private final @NotNull LuaFunction function; + + public LuaFunctionWrapper(@NotNull LuaFunction function) { + this.function = function; + } + + @Override + public int __call(Lua L) { + LuaValue[] args = new LuaValue[L.getTop()]; + for (int i = 0; i < args.length; i++) { + args[args.length - i - 1] = L.get(); + } + LuaValue[] results = function.call(L, args); + if (results != null) { + for (LuaValue result : results) { + L.push(result); + } + } + return results == null ? 0 : results.length; + } + } } diff --git a/luajava/src/main/java/party/iroiro/luajava/Lua.java b/luajava/src/main/java/party/iroiro/luajava/Lua.java index 00e16692..1bac4be0 100644 --- a/luajava/src/main/java/party/iroiro/luajava/Lua.java +++ b/luajava/src/main/java/party/iroiro/luajava/Lua.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import party.iroiro.luajava.value.LuaFunction; import party.iroiro.luajava.value.LuaThread; import party.iroiro.luajava.value.LuaValue; @@ -149,6 +150,21 @@ public interface Lua extends AutoCloseable, LuaThread { */ void pushJavaClass(@NotNull Class clazz); + /** + * Push a {@link LuaValue} onto the stack, equivalent to {@link LuaValue#push(Lua)} + * + * @param value the value + */ + void push(@NotNull LuaValue value); + + /** + * Push the function onto the stack, converted to a callable element + * + * @param value the function + * @see #push(JFunction) + */ + void push(@NotNull LuaFunction value); + /** * Push the element onto the stack, converted as is to Java objects * diff --git a/luajava/src/main/java/party/iroiro/luajava/value/LuaFunction.java b/luajava/src/main/java/party/iroiro/luajava/value/LuaFunction.java new file mode 100644 index 00000000..4735a97f --- /dev/null +++ b/luajava/src/main/java/party/iroiro/luajava/value/LuaFunction.java @@ -0,0 +1,22 @@ +package party.iroiro.luajava.value; + +import party.iroiro.luajava.Lua; + +/** + * Interface for functions implemented in Java. + */ +public interface LuaFunction { + /** + * Implements the function body + * + *

+ * Unlike {@link party.iroiro.luajava.JFunction#__call(Lua)}, before actually calling this function, + * the library converts all the arguments to {@link LuaValue LuaValues} and pops them off the stack. + *

+ * + * @param L the Lua state + * @param args the arguments + * @return the return values (nullable) + */ + LuaValue[] call(Lua L, LuaValue[] args); +} diff --git a/luajava/src/main/java/party/iroiro/luajava/value/LuaThread.java b/luajava/src/main/java/party/iroiro/luajava/value/LuaThread.java index 22ed3d64..99cd298a 100644 --- a/luajava/src/main/java/party/iroiro/luajava/value/LuaThread.java +++ b/luajava/src/main/java/party/iroiro/luajava/value/LuaThread.java @@ -1,7 +1,6 @@ package party.iroiro.luajava.value; import org.jetbrains.annotations.Nullable; -import party.iroiro.luajava.JFunction; import party.iroiro.luajava.LuaException; public interface LuaThread { @@ -27,7 +26,7 @@ public interface LuaThread { * @param name the global name * @param function the function */ - void register(String name, JFunction function); + void register(String name, LuaFunction function); /** * Executes Lua code