Luaj:如何导入或需要Lua函数库 [英] Luaj: How to Import or Require a Lua Function Library

查看:211
本文介绍了Luaj:如何导入或需要Lua函数库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Java LuaJ库中,我想知道如何要求或导入lua脚本通过Java的lua闭包调用的另一个lua脚本中的函数集合.例如,这不起作用:

In the Java LuaJ library I would like to know how to require or import a lua script of functions in another lua script called by a lua closure through Java. For example this does not work:

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的内容:

And the input stream here refers to the contents of another lua:

import 'mycoolmathfunctions'
-- or maybe require mycoolmathfunctions ?

return sum({1, 2, 3})
-- or maybe mycoolmathfunctions.sum({1, 2, 3}) ?

我该怎么做?

推荐答案

在Java LuaJ库中,我想知道如何在Java的lua闭包调用的另一个lua脚本中要求或导入函数的lua脚本.

In the Java LuaJ library I would like to know how to require or import a lua script of functions in another lua script called by a lua closure through Java.

您可以将Lua库作为资源放置在Java包中.然后在需要另一个lua脚本的lua脚本上,相对于包路径require将它们require

You can place your Lua libraries as resources in your Java packages. Then on your lua script that requires another lua script, you require them relative to your package path.

这是一个例子:

这是我们的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中:

Which is then imported in our sample-that-imports.lua:

require "com.example.import-me"

my_imported.printHello()

然后我们在SampleMain Java类中运行sample-that-imports.lua:

Then we run our sample-that-imports.lua in our SampleMain Java class:

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();
    }
}


现在要回答您的其他问题,


Now to answer your other problems,

例如,这不起作用…

For example this does not work…

我在您的Java代码中注意到,您已经假设调用loadfile()会自动运行lua脚本.此外,您已假定loadfile()用于加载lua模块.但是,这不是应该使用的方式.

I've noticed on your Java code that you've assumed that calling loadfile() would automatically run your lua script. Furthermore, you've assumed that loadfile() is used for loading your lua modules. However, this isn't how it is supposed to be used.

您的loadfile()应该能够返回call()来运行脚本本身所需的LuaValue.您甚至可以安全地将其强制转换为LuaClosure,因为这是loadfile()实际返回的内容.

Your loadfile() should be able to return a LuaValue that you need to call() to run the script itself. You could even safely cast it to a LuaClosure because this is what loadfile() actually returns.

要在上面修复Java代码,您可以使用它,

To fix your Java code above, you can use this,

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();
}

我将在上面的代码中假设您已经在使用上述方法传递的InputStream(包含lua脚本)中使用了require.如果不是,则可以进行以下更改:

I will assume in the above code that you are already using require in the InputStream (containing a lua script) that you have passed with the above method. If not then, you can do the following changes:

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表).如果没有,您可以做最后的修饰:

In the above changes, I am assuming that your lua module (in our example import-me.lua) automatically creates a global space for itself (in our example, the my_imported table). If not, you could do this final touch:

...
LuaValue chunk = globals.load("my_imported = require 'com.example.import-me';");
...


除非您真的想在每次调用方法时都创建一个新的Globals表,否则还应该重用Globals(由JsePlatform.standardGlobals()返回).此外,如果您真的不需要InputStream,而只想从文件路径(或Java包路径中的资源路径)加载文件本身,则可以简化以下内容:


You also should reuse your Globals (returned by JsePlatform.standardGlobals()) unless you really want to create a new Globals table every time you call your method. Furthermore, if you really don't need an InputStream, and simply wants to load the file itself from its file path (or resource path in your Java package path), you can simplify everything into this:

public static LuaValue runLuaFile(Globals globals, String luafile) {
    return globals.loadfile(luafile).call();
}

或者要确保我们的lua模块始终由我们的lua脚本导入(或已经被require'd),

Or to ensure that our lua module is always imported (or has been require'd) by our lua script,

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代码段:

Again, you must specify the complete resource path for our lua file. Here's a sample Java snippet using our simplified method above:

Globals globals = JsePlatform.standardGlobals();
runLuaFile(globals, "com/example/sample-that-imports.lua");

我希望这会有所帮助!

您在注释中提到需要从InputStream导入lua模块.有两种方法可以实现:

You've mentioned in the comments that you need to import lua modules from InputStreams. There are 2 ways to achieve that:

  1. 第一个是加载和运行所需的lua模块,例如简单的lua脚本–并且如果您所需的lua模块仅与lua的require机制兼容,那么您将拥有很多要面对的问题.
  2. 第二种,最简单,最有效的方法是简单地加载模块,将其放置在lua表package.preload中,该表以键名映射(供require使用).
  1. The first one is to load and run the lua modules that you need, like simple lua scripts – and if case that the lua modules that you need are only compatible with lua's require mechanism, you'll have a lot of problems to face.
  2. The second, easiest, and most efficient way is to simply load the module, place it inside the lua table package.preload, mapped with a key as its name (to be used by require).

我们将使用上面的第二种方法,因为这正是lua的require机制的真正意图.这是使用LuaJ实施的方法:

We'll use the second method above, as this is exactly what lua's require mechanism really intends. Here's how to implement it using 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);
}

上述实用程序方法会预加载供require使用的InputStream.这是一个示例用法:

The above utility method pre-loads an InputStream to be used by require. Here's an example usage:

在一切开头的某个地方,我们初始化了东西:

Somewhere in the beginning of everything, we initialize stuffs:

...
preloadLuaModule(globals, "sample_module", sampleModuleInputStream);
...

我们上面的sampleModuleInputStream是一个lua模块,其内容如下:

And our sampleModuleInputStream above is a lua module with the following content:

-- make our sample module table global
sample_module = {}

function sample_module.printHi()
    print "Hi!"
end

return sample_module

然后,我们可以在任何我们喜欢的地方简单地使用require "sample_module",无论是在Lua脚本中还是在Java中使用LuaJ:

Then we could simply use require "sample_module" anywhere we like, be it in a Lua script or in Java using LuaJ:

globals.get("require").call("sample_module");

这篇关于Luaj:如何导入或需要Lua函数库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆