【问题标题】:LuaJ - Calling a Java methodLuaJ - 调用 Java 方法
【发布时间】:2016-04-12 10:12:03
【问题描述】:

我有一个带有名为 test 的方法的 Java 类:

public class MyClass() {
    public String test() {
        //Do Something
    }
}

然后,我想在我的 Lua 脚本中调用测试方法。为了做到这一点,我做了:

Globals globals = JsePlatform.standartGlobals();

LuaValue test = CoerceJavaToLua.coerce(new MyClass());
globals.set("obj", test);
LuaValue chunk = globals.load("obj.test()");
chunk.call();

当调用 Lua 脚本时,我得到了一个错误的参数错误。

仅当我使用“obj:test()”时才有效。

就像我应该在第一个参数中传递对象。

有没有办法让“obj.test()”工作?

【问题讨论】:

  • 如果方法是静态的,那么它可能会起作用。目前您的方法不是静态的,因此它需要一个 MyClass 的实例作为第一个参数传递,并且使用 : 只是将 obj 作为第一个参数传递给 obj.test 的语法糖
  • 如何将 MyClass 及其功能暴露给 luaj?
  • 有了这个:LuaValue test = CoerceJavaToLua.coerce(new MyClass()); globals.set("obj", test);

标签: java lua luaj


【解决方案1】:

你也可以使用等价的语法:

obj.test(obj)

一样
obj:test()

您应该能够获取 Java 类或实例的任何字段或方法,但在某些情况下需要额外的参数,而冒号语法是一种方便的快捷方式。

为了说明,构造一个具有各种静态和实例字段和方法的类,例如:

public static class MyClass {
    public static String variable = "variable-value";
    public String field = "field-value";
    public static String func() {
        return "function-result";
    }
    public String method() {
        return "method-result";
    }

如果您像示例中那样强制该类的一个实例,以下是访问每个类的语法:

Globals globals = JsePlatform.standardGlobals();

// Load an instance into globals
LuaValue instance = CoerceJavaToLua.coerce(new MyClass());
globals.set("obj", instance);
LuaValue chunk = globals.load(
        "print( obj );" +
        "print( obj.variable );" +
        "print( obj.field );" +
        "print( obj.func );" +
        "print( obj.method );" +
        "print( obj:method() );" + // same as 'obj.method(obj)'
        "print( obj.method(obj) );");
chunk.call();   

为我制作的

Example$MyClass@4554617c
variable-value
field-value
function: JavaMethod
function: JavaMethod
method-result
method-result

您可能还想强制上课。除了类不存在的字段之外,仍然可以访问所有内容:

// Load a class into globals, 'field' cannot be accessed
LuaValue cls = CoerceJavaToLua.coerce(MyClass.class);
globals.set("cls", cls);
chunk = globals.load(
        "print( cls );" +
        "print( cls.variable );" +
        "print( cls.func );" +
        "print( cls:func() );" + // same as 'cls.method(cls)'
        "print( cls.func(cls) );" +
        "print( cls.method );" +
        "print( cls.method(obj) );"); 
chunk.call();   

输出是:

class Example$MyClass
variable-value
function: JavaMethod
function-result
function-result
function: JavaMethod
method-result

在 lua 中,可以通过“new”从 Java 类构造一个实例,然后它的行为类似于其他 Java 实例:

// Construct an instance from a class using 'new'
chunk = globals.load(
        "print( cls.new );" +   
        "print( cls.new() );" +
        "print( cls.new().field );"); // etc.
chunk.call();   

输出是

function: JavaConstructor
Example$MyClass@4b67cf4d
field-value

【讨论】:

    【解决方案2】:

    我找不到任何绑定类的静态函数并在没有类实例的情况下调用它的示例。 任何地方的所有示例,即使在使用静态函数时,都传递对象的实例。 因此,我不能 100% 确定这是不可能的(不编辑 luaj)。

    库和示例中的任何静态函数实际上都是通过创建一个虚拟类来创建的,例如参见此处http://luaj.cvs.sourceforge.net/viewvc/luaj/luaj-vm/examples/jse/hyperbolic.java?view=markup

    仔细查看 luaj 源代码会发现,luaj 并没有区分类中的静态函数和非静态函数,这意味着所有函数都作为非静态函数处理。更多信息见JavaClass.javagetMethod函数。

    这是一个相当简单的例子,你可以如何完成你想要的,但遗憾的是它需要没有静态方法。

    package luaj;
    
    import org.luaj.vm2.*;
    import org.luaj.vm2.lib.*;
    import org.luaj.vm2.lib.jse.*;
    
    public class luaj {
    
        static final public class MyClass {
    
            public static int asd = 5;
    
            static public class Test extends ZeroArgFunction {
    
                @Override
                public LuaValue call() {
                    System.out.println("Worked");
                    return NIL;
                }
            }
        }
    
        public static void main(String[] args) {
            Globals globals = JsePlatform.standardGlobals();
            LuaValue test = CoerceJavaToLua.coerce(new MyClass());
            globals.set("obj", test);
            LuaTable t = new LuaTable();
            t.set("test", new MyClass.Test());
            t.set("__index", t);
            test.setmetatable(t);
            LuaValue chunk = globals.load("print('Testing', obj.asd) obj.test()");
            chunk.call();
        }
    }
    

    通过将obj.test 设置为包装真实obj.test 的函数并将MyClass 的新实例传递给它,从而“隐藏”实例的传递,可以使用静态方法完成类似的方法.

    【讨论】:

      【解决方案3】:

      我不怎么做lua,但是你说你必须做的就是有效的

      LuaValue chunk = globals.load("obj:test()");
      

      注意冒号,这就是方法的调用方式。

      就像我说的,我做的不多,但看起来你必须这样做

      【讨论】:

      • 很遗憾,我无法更改脚本。我必须在不传递对象的情况下执行它。
      猜你喜欢
      • 2012-02-15
      • 2013-03-16
      • 2012-06-30
      • 2014-12-21
      • 2015-01-12
      • 1970-01-01
      • 2013-04-06
      • 2015-01-27
      • 2016-07-26
      相关资源
      最近更新 更多