Search code examples
arrayslualuajava

LuaJava indexing Java arrays in Lua


In my application, I need my lua script to index a java array. For some reason I don't understand, I can't index the array at all within Lua. Here is my Lua file (test_lua.lua): https://pastebin.com/zQUPVArz

Here is the Java file calling this code (experiment.Experimental.class): https://pastebin.com/Gr9EsvbM

And here is the Bobject interface: https://pastebin.com/agdS41sc

Using this method, I am unable to do anything with Java arrays from Lua. I even tried using reflection and CoerceLuaToJava to index the array, but to no avail. Below is the offending Lua code:

behavior_table.doArray = function(array)
    print("Length:", array.length)              -- Prints array length correctly
    print(array)                                -- Prints the array using toString(), resulting in [Ljava.lang.Object;@2d363fb3
    print(array[0])                             -- prints 'nil'
    Array = luajava.bindClass("java.lang.reflect.Array")
    Coerce = luajava.bindClass("org.luaj.vm2.lib.jse.CoerceLuaToJava")
    array[0] = 4                                -- Throws a LuaError: index expected, got userdata
    print(array[0])                             -- prints 'nil', as before
    print(Array.get(Coerce.coerce(array), 0))   -- Throws a NullPointerException
end

Prior to this code, I also tried loading the behavior_table itself as a LuaTable object in Java, using explicitly typed coercions, with something like this:

table.get("doArray").invoke(new LuaValue[]{
    CoerceJavaToLua.coerce(array)
}).arg1()

...Thus calling the function from the table and coercing the Java objects myself, as opposed to having the script return a Bobject instance with overidden functions. This method didn't change the outcome at all.

Am I just using the improper syntax for indexing the coerced array? I feel like it's being coerced properly, given that I can print it using toString() and access its length. I think the array is coerced into a lua table, correct? If that's the case, how do I index its values? I'm still very new to the concept of Lua's "tables"

Thank you for your time.


Solution

  • Once again, I managed to solve my own issue in the end. I read up on Lua tables and found my way to this stack overflow question: Open Arrays or ArrayLists in Lua (Convert array to table)

    I ended up writing a method in Java to coerce each individual object in my Java array, and place it into a LuaTable object. I called this method from my Lua script and was able to manipulate it as I wished.

    I included a bit of recursion that coerces multi-dimensional arrays, by checking if array[i] instanceof Object[]

    Here's the code I wrote in Java:

    public static LuaTable arrayToTable(Object[] array) {
        LuaTable result = new LuaTable();
    
        for(int i = 0; i < array.length; ++i)
            if(array[i] instanceof Object[])
                result.set(i, arrayToTable((Object[])array[i]));
            else
                result.set(i, CoerceJavaToLua.coerce(array[i]));
    
        return result;
    }
    

    With luautils being a binding to the class with my arrayToTable method, I'm able to manipulate any value from my lua script like this:

    function behavior.update(entity, world, elapsed)
        e = luautils:arrayToTable(world:getComponents()) 
        -- getComponents() returns a 3-dimensional Java array
        transform = e[1][0][0]
        print("XPOS is: ", transform.xpos)
        transform.xpos = transform.xpos + 1
    end
    

    Output:

    XPOS is:    20
    XPOS is:    21
    XPOS is:    22
    

    ...and so on.