Overv
Overv

Reputation: 8519

Method of binding Java functions to Lua?

I'm working on a Lua wrapper for my Android app, which will allow me to write Lua code to speed up development. I've made a static class called lua with functions like newState and pushString. I manage the Lua state by passing around a long with the pointer to the lua_State. As you can tell, I don't need any fancy stuff that makes interaction easier, like overloads to push variables.

Now, the problem is binding Java functions to Lua variables. I've thought of a few ways to do this, but they're all ugly.

  1. Instead of functions, pass around a table with a reference to the Java function as a userdatum and have a __call metamethod take care of calling the "function".

  2. Alter Lua internals to include a Java reference with Lua C functions.

Is there any better way to go about this? Or should I go with the second method? (I realise the first method is ridiculous, but it manifested itself in my mind as a solution anyways.)

Upvotes: 1

Views: 3161

Answers (3)

Overv
Overv

Reputation: 8519

I decided to use lua_pushcclosure, as it allows you to 'store' arbitrary values on functions that can be retrieved with the lua_upvalueindex macro.

Upvotes: 1

Michal Kottman
Michal Kottman

Reputation: 16763

You can have a look at my simple project AndroLua. It contains Lua and LuaJava compiled using the Android NDK.

Because it uses LuaJava, it allows to bind Java functions to Lua, in a similar way like you said, using userdata. Here is an example of how I override the print function to output text into a TextView:

JavaFunction print = new JavaFunction(L) {
    @Override
    public int execute() throws LuaException {
        StringBuilder sb = new StringBuilder();
        for (int i = 2; i <= L.getTop(); i++) {
            int type = L.type(i);
            String val = L.toString(i);
            if (val == null)
                val = L.typeName(type);
            sb.append(val);
            sb.append("\t");
        }
        sb.append("\n");
        status.append(sb.toString());
        return 0;
    }
};
print.register("print");

The downside is that sometimes you cannot pass the print as a function parameter (because it is a userdata, even though it has a __call metamethod). Fortunately, it can be solved in Lua by creating a pure Lua function, like this:

do
    local oldprint = print
    function print(...) oldprint(...) end
end

Upvotes: 5

Related Questions