0
votes

I figured out how to make Lua scripts require other Lua scripts in an Android environment.

However, that solution has the package.path configuration inside the top level Lua script itself. I want to move the package.path configuration to the Java code that runs the script instead, because the package.path is specific to the Android environment, while the script could be run anywhere.

Here is what I've tried:

InputStream input getAssets().open("lua/test/pathTest.lua");
Prototype prototype = LuaC.instance.compile(input, "pathTest.lua");
Globals globals = JsePlatform.standardGlobals();
globals.load(new BaseLib());
globals.load("package.path = package.path .. ';/assets/lua/?.lua;/assets/lua/test/?.lua'");

LuaClosure c = new LuaClosure(prototype, globals);
c.call();

I've also tried a few other forms like:

globals.load(new StringReader("package.path = package.path .. \";/assets/lua/?.lua;/assets/lua/test/?.lua\""), "pathTest.lua");

Or taking the LuaValue result from the load and passing that to the LuaClosure. They all result in the script failing at the first require, not being able to find the referenced script.

Anyone have any ideas?

*edit - If anyone knows how to set the working directory to the /assets/lua/ folder, so I can use relative paths from there in the Lua script, that would be preferable.

2

2 Answers

1
votes

Thought I had tried this before, but here's the solution.

InputStream input getAssets().open("lua/test/pathTest.lua");
Prototype prototype = LuaC.instance.compile(input, "pathTest.lua");
Globals globals = JsePlatform.standardGlobals();
globals.load(new BaseLib());
globals.load(new StringReader("package.path = '/assets/lua/?.lua;'"), "initAndroidPath").call();

LuaClosure c = new LuaClosure(prototype, globals);
c.call();

That will initialize the Android environment's path to the assets/lua/ folder. This allows me to use relative paths in the require call in the Lua script.

For example, to require a file in subdirectory: assets/lua/test/luaScript.lua

The Lua require would look like:

require "test.luaFile"
0
votes

At the basis of mnemy's solution, add some content. The default findResource method definition is (PS: In the BaseLib.java of luaj source code):

public InputStream findResource(String filename) {
    return getClass().getResourceAsStream(filename.startsWith("/")? filename: "/"+filename);
}

Android's getResourceAsStream method search resource relative to the android project's root directory. (I solved a classloader problem with the link LuaJ and Android: cannot bind class, Cloudy Zheng's solution.) So, if you want use "requre" to load other module in other directory(e.g. "/storage/emulated/0/temp/test/lua"), you could implement your own findResource interface like this:

// Implement a finder that loads from absolute path.
public InputStream findResource(String name) {
    try {
        File f = new File(name);
        return new FileInputStream(f);
    } catch (java.io.IOException ioe) {
        return null;
    }
}

And set as your globals.finder. Then adjust the search path accordingly:

globals.load(new StringReader("package.path = '/storage/emulated/0/temp/test/lua/?.lua;'"), "initAndroidPath").call();