Reputation: 79
I have a Java Class with a method called test:
public class MyClass() {
public String test() {
//Do Something
}
}
Then, I want to call the test method in my Lua script. In order to do it, I did:
Globals globals = JsePlatform.standartGlobals();
LuaValue test = CoerceJavaToLua.coerce(new MyClass());
globals.set("obj", test);
LuaValue chunk = globals.load("obj.test()");
chunk.call();
When the Lua script is called, I got a bad argument error.
It only works when I use "obj:test()".
It's like I should pass the object in the first parameter.
Is there a way to do "obj.test()" work?
Upvotes: 4
Views: 7836
Reputation: 201
You can also use the equivalent syntax:
obj.test(obj)
It's the same as
obj:test()
You should be able to get at any filed or method of a Java class or instance, but in certain cases the extra argument is required, and the colon syntax is a convenient shortcut.
To illustrate, construct a class with various static and instance fields and methods such as this:
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";
}
If you coerce an instance of that class as in your example, here is syntax to access each:
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();
which for me produced
Example$MyClass@4554617c
variable-value
field-value
function: JavaMethod
function: JavaMethod
method-result
method-result
You may also want to just coerce the class instead. Everything can still be accessed except the field, which doesn't exist for a class:
// 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();
The output is:
class Example$MyClass
variable-value
function: JavaMethod
function-result
function-result
function: JavaMethod
method-result
Within lua, an instance can be constructed from a Java class via 'new', then it behaves like other Java instances:
// Construct an instance from a class using 'new'
chunk = globals.load(
"print( cls.new );" +
"print( cls.new() );" +
"print( cls.new().field );"); // etc.
chunk.call();
and the output is
function: JavaConstructor
Example$MyClass@4b67cf4d
field-value
Upvotes: 3
Reputation: 1156
I can't find any examples of binding a static function of a class and calling it without an instance of the class. All examples everywhere, even when using static functions, pass an instance of the object. Thus I can not be 100% sure this is not possible to do (without editing luaj).
Any static functions in libraries and examples are actually made with creating a dummy class for example see here http://luaj.cvs.sourceforge.net/viewvc/luaj/luaj-vm/examples/jse/hyperbolic.java?view=markup
A closer look at the luaj source shows that luaj does not distinct between static and nonstatic functions in a class which means all are handled as nonstatic. See JavaClass.java
getMethod
function for more.
Here is a rather simple example how you can accomplish what you wanted, but sadly it requires to not have a static method.
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();
}
}
A similar approach can probably be done with using a static method by setting obj.test
to a function that wraps the real obj.test
and passes a new instance of MyClass
to it thus "hiding" the passing of an instance.
Upvotes: 3
Reputation: 33
I dont do lua that much, but what you said you have to do is what works
LuaValue chunk = globals.load("obj:test()");
notice the colon, thats how the method should be called.
Like I said, I don't do much, but it looks like the way you have to do it is in that way
Upvotes: 0