java - Luaj: Cómo importar o requerir una biblioteca de funciones Lua
(1)
En la biblioteca de Java LuaJ me gustaría saber cómo requerir o importar un script de lua de funciones en otro script de lua llamado por un cierre de lua a través de Java. Por ejemplo, esto no funciona:
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();
}
Y el flujo de entrada aquí se refiere al contenido de otra lua:
import ''mycoolmathfunctions''
-- or maybe require mycoolmathfunctions ?
return sum({1, 2, 3})
-- or maybe mycoolmathfunctions.sum({1, 2, 3}) ?
¿Cómo hago esto?
En la biblioteca de Java LuaJ me gustaría saber cómo requerir o importar un script de lua de funciones en otro script de lua llamado por un cierre de lua a través de Java.
Puede colocar sus bibliotecas Lua como recursos en sus paquetes de Java. Luego, en su script de lua que requiere otro script de lua, los require
en relación con la ruta de su paquete.
Aquí hay un ejemplo:
Aquí está nuestro import-me.lua
:
-- make our sample module table global
my_imported = {}
function my_imported.printHello()
print "Hello!"
end
return my_imported
Que luego se importa en nuestro sample-that-imports.lua
:
require "com.example.import-me"
my_imported.printHello()
Luego ejecutamos nuestro sample-that-imports.lua
en nuestra clase SampleMain
Java:
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();
}
}
Ahora para responder a tus otros problemas,
Por ejemplo, esto no funciona ...
He notado en tu código Java que loadfile()
que llamar a loadfile()
ejecutaría automáticamente tu script lua. Además, ha asumido que loadfile()
se usa para cargar sus módulos lua. Sin embargo, esta no es la forma en que se debe utilizar.
Su loadfile()
debería poder devolver un LuaValue
que necesita call()
para ejecutar el script en sí. Incluso podrías LuaClosure
forma segura a un LuaClosure
porque esto es lo que realmente devuelve loadfile()
.
Para arreglar su código Java anterior, puede usar esto,
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();
}
Asumiré en el código anterior que ya está utilizando require
en el InputStream
(que contiene un script lua) que ha pasado con el método anterior. Si no es así, puedes hacer los siguientes cambios:
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();
}
En los cambios anteriores, import-me.lua
que su módulo lua (en nuestro ejemplo import-me.lua
) crea automáticamente un espacio global para sí mismo (en nuestro ejemplo, la tabla my_imported
). Si no, puedes hacer este toque final:
...
LuaValue chunk = globals.load("my_imported = require ''com.example.import-me'';");
...
También debe reutilizar sus Globals
(devueltos por JsePlatform.standardGlobals()
) a menos que realmente desee crear una nueva tabla de Globals
cada vez que llame a su método. Además, si realmente no necesita un InputStream
, y simplemente quiere cargar el archivo desde su ruta de archivo (o la ruta de recursos en la ruta de su paquete Java), puede simplificar todo esto:
public static LuaValue runLuaFile(Globals globals, String luafile) {
return globals.loadfile(luafile).call();
}
O para asegurarnos de que nuestro módulo lua siempre sea importado (o haya sido require
''d) por nuestro script lua,
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();
}
Nuevamente, debe especificar la ruta completa de recursos para nuestro archivo lua. Aquí hay un fragmento de código de muestra de Java que utiliza nuestro método simplificado de arriba:
Globals globals = JsePlatform.standardGlobals();
runLuaFile(globals, "com/example/sample-that-imports.lua");
¡Espero que esto ayude!
Editar:
Ha mencionado en los comentarios que necesita importar módulos lua desde los InputStream
s. Hay 2 formas de lograrlo:
- El primero es cargar y ejecutar los módulos de lua que necesita, como los simples scripts de lua, y en caso de que los módulos de lua que necesita solo sean compatibles con el mecanismo de lua, tendrá que enfrentar muchos problemas.
- La segunda forma, la más sencilla y la más eficiente es simplemente cargar el módulo, colocarlo dentro del
package.preload
lua tablepackage.preload
, mapeado con una clave como su nombre (para ser usado porrequire
).
Usaremos el segundo método anterior, ya que esto es exactamente lo que realmente pretende el mecanismo de exigencia de lua. Aquí está cómo implementarlo usando 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);
}
El método de utilidad anterior carga previamente un InputStream
para ser utilizado por require
. Aquí hay un ejemplo de uso:
En algún lugar al principio de todo, inicializamos cosas:
...
preloadLuaModule(globals, "sample_module", sampleModuleInputStream);
...
Y nuestro sampleModuleInputStream
anterior es un módulo lua con el siguiente contenido:
-- make our sample module table global
sample_module = {}
function sample_module.printHi()
print "Hi!"
end
return sample_module
Entonces podríamos simplemente usar require "sample_module"
cualquier lugar que require "sample_module"
, ya sea en un script Lua o en Java usando LuaJ
globals.get("require").call("sample_module");