2

I want to return an instance of a Java class as userdata to my lua script. Would it be possible to access properties and functions of this instance from lua?

Like so

local car = Car.getNew()
print(car.hasHonked)
car:honk()
print(car.hasHonked)

That's my attempt to solve the problem

Java (shortened)

public class CarModule extends TwoArgFunction {

    String moduleName = "Car";

    public LuaValue call(LuaValue modname, LuaValue env) {
        LuaValue library = new LuaTable();
        library.set("getNew", new getNew());
        env.set(moduleName, library);
        return library;
    }

    static class getNew extends ZeroArgFunction {
        @Override
        public LuaValue call() {
            return LuaValue.userdataOf(new Car());
        }
    }    
}

public class Car {
    private int count;

    @Override
    public String toString() {
        return "Hello World";
    }

    public void honk() {
        count++;
    }

    public int getHonks() {
        return count;
    }
}

lua

local car = Car.getNew()
print(car) -- foo.bar.lua.module.CarModule$Car@1ef7fe8e
print(type(car)) -- = userdata
print(car.honk) -- = nil
print(car.getHonks) -- = nil
print(car:honk) -- = LuaError: function arguments expected
print(car:getHonks) -- = LuaError: function arguments expected
print(tostring(car)) -- = Hello World
car:honk() -- = LuaError: attempt to call nil
car:getHonks() -- = LuaError: attempt to call nil

Edit:

Found the answer here

Instead of

return LuaValue.userdataOf(new Car());

I have to use

return CoerceJavaToLua.coerce(new Car());
Community
  • 1
  • 1
boop
  • 7,413
  • 13
  • 50
  • 94

1 Answers1

1

You can try link the access to car.hasHonked to a function that returns the value from java. I have not used luaj so I cannot comment on how exactly that would be done with it, but here is the same principle done with lua. All you need to do is replace the __index function to something that accesses your variables. The code uses metatables to allow the linking of not found keys to a function.

Car = {}
function Car.__index(table, key)
    print(Car, table, key)
    return "the java value according to key"
end
function Car.getNew()
    return setmetatable({}, Car) -- sets metatable for userdata or table
end

local car = Car.getNew()

print(car.hasHonked)
-- prints:
-- table: 0xa64f80  table: 0xa6e370 hasHonked
-- the java value according to key

Another option could be just using functions directly like below. These functions would call to java and return the real java value.

car = {}
function car.getHonked()
    return "the java value"
end
Rochet2
  • 1,146
  • 1
  • 8
  • 13