在Java LuaJ library中,我想知道如何通过Java在lua闭包调用的另一个lua脚本中要求或导入函数的lua脚本。例如,这不起作用:
public static LuaValue runInputStreamLua(InputStream inputStream) throws Exception {
Prototype luaScriptPrototype = LuaC.instance.compile(inputStream, "");
Globals luaScriptStandardGlobals = JsePlatform.standardGlobals();
luaScriptStandardGlobals.loadfile("mycoolmathfunctions.lua");
LuaClosure luaClosure = new LuaClosure(luaScriptPrototype, luaScriptStandardGlobals);
return luaClosure.call();
}
这里的输入流是指另一个lua的内容:
import 'mycoolmathfunctions'
-- or maybe require mycoolmathfunctions ?
return sum({1, 2, 3})
-- or maybe mycoolmathfunctions.sum({1, 2, 3}) ?
我该怎么做?
答案 0 :(得分:12)
在Java LuaJ库中,我想知道如何通过Java在lua闭包调用的另一个lua脚本中要求或导入函数的lua脚本。
您可以将Lua库作为资源放在Java包中。然后在你需要另一个lua脚本的lua脚本上,你require
相对于你的包路径。
以下是一个例子:
这是我们的import-me.lua
:
-- make our sample module table global
my_imported = {}
function my_imported.printHello()
print "Hello!"
end
return my_imported
然后在sample-that-imports.lua
:
require "com.example.import-me"
my_imported.printHello()
然后我们在sample-that-imports.lua
Java类中运行SampleMain
:
package com.example;
...
public class SampleMain {
public static void main(String[] args) {
Globals globals = JsePlatform.standardGlobals();
// Again, we load the lua scripts relative to our package path
LuaValue chunk = globals.loadfile("com/example/sample-that-imports.lua");
chunk.call();
// We could even use our imported library here
chunk = globals.load("my_imported.printHello()");
chunk.call();
}
}
现在回答你的其他问题,
例如,这不起作用......
我已经注意到您的Java代码,您已经认为调用loadfile()
会自动运行您的lua脚本。此外,您已假设loadfile()
用于加载您的lua模块。但是,这不是应该如何使用的。
您的loadfile()
应该能够返回LuaValue
所需的call()
来运行脚本本身。您甚至可以安全地将其转换为LuaClosure
,因为这是loadfile()
实际返回的内容。
要修复上面的Java代码,可以使用
public static LuaValue runInputStreamLua(InputStream inputStream) throws Exception {
Prototype luaScriptPrototype = LuaC.instance.compile(inputStream, "");
Globals globals = JsePlatform.standardGlobals();
LuaClosure luaClosure = new LuaClosure(luaScriptPrototype, globals);
return luaClosure.call();
}
我将在上面的代码中假设您已经在使用上述方法传递的require
(包含lua脚本)中使用InputStream
。如果没有,您可以进行以下更改:
public static LuaValue runInputStreamLua(InputStream inputStream) throws Exception {
Prototype luaScriptPrototype = LuaC.instance.compile(inputStream, "");
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load("require 'com.example.import-me';");
chunk.call();
LuaClosure luaClosure = new LuaClosure(luaScriptPrototype, globals);
return luaClosure.call();
}
在上面的更改中,我假设您的lua模块(在我们的示例中为import-me.lua
)自动为自己创建一个全局空间(在我们的示例中为my_imported
表)。如果没有,你可以做最后的决定:
...
LuaValue chunk = globals.load("my_imported = require 'com.example.import-me';");
...
您还应该重复使用Globals
(由JsePlatform.standardGlobals()
返回),除非您真的想在每次调用方法时创建一个新的Globals
表。此外,如果您真的不需要InputStream
,并且只想从文件路径(或Java包路径中的资源路径)加载文件本身,您可以将所有内容简化为:
public static LuaValue runLuaFile(Globals globals, String luafile) {
return globals.loadfile(luafile).call();
}
或者确保我们的lua模块总是被我们的lua脚本导入(或已经require
&#d; d),
public static LuaValue runLuaFile(Globals globals, String luafile) {
LuaValue chunk = globals.load("require 'com.example.import-me';");
chunk.call();
chunk = globals.loadfile(luafile);
return chunk.call();
}
同样,您必须为我们的lua文件指定完整的资源路径。以下是使用上述简化方法的示例Java代码段:
Globals globals = JsePlatform.standardGlobals();
runLuaFile(globals, "com/example/sample-that-imports.lua");
我希望这有帮助!
您在评论中提到需要从InputStream
导入lua模块。有两种方法可以实现这一目标:
require
机制兼容,你和& #39;要面对很多问题。package.preload
内,用键作为其名称进行映射(由require
使用)。 我们将使用上面的第二种方法,因为这正是lua' require
机制的真正含义。以下是使用LuaJ实现它的方法:
public static void preloadLuaModule(Globals globals, String modname, InputStream is) {
LuaValue module = globals.load(is, modname, "bt", globals);
globals.get("package").get("preload").set(modname, module);
}
上述实用程序方法预加载InputStream
以供require
使用。以下是一个示例用法:
在一切开始的某个地方,我们初始化东西:
...
preloadLuaModule(globals, "sample_module", sampleModuleInputStream);
...
我们上面的sampleModuleInputStream
是一个包含以下内容的lua模块:
-- make our sample module table global
sample_module = {}
function sample_module.printHi()
print "Hi!"
end
return sample_module
然后我们可以在任何我们喜欢的地方使用require "sample_module"
,无论是在Lua脚本中还是在使用LuaJ的Java中:
globals.get("require").call("sample_module");