luaj是lua的一个java版本的实现。使用luaj可以在java程序中允许lua程序。这给java带来了脚本功能。luaj对javase 和Android 都提供了支持。
下面第一个例子,使用java加载lua脚本并执行。
main.java 文件内容:
String script = "hello.lua";
// create an environment to run in
//初始化lua运行时环境
Globals globals = JsePlatform.standardGlobals();
// Use the convenience function on Globals to load a chunk.
//通过Globals加载lua脚本
LuaValue chunk = globals.loadfile(script);
// Use any of the "call()" or "invoke()" functions directly on the chunk.
//运行lua脚本
chunk.call( LuaValue.valueOf(script) );
hello.lua 文件内容:
print("hello luaj !!!")
在两种语言交互使用中,就存在几个方面的内容:1 -两种语言中基本数据类型的映射 2 -两种语言中函数的相互调用 3- 语言的内存管理
在这篇中我们主要关注luaj怎么来表达lua语言以及luaj的使用。
在Luaj中我们首先关注的类为Globals,该类用来初始化lua 虚拟机以及加载lua脚本。
/**
* Create a standard set of globals for JSE including all the libraries.
*
* @return Table of globals initialized with the standard JSE libraries
* @see #debugGlobals()
* @see org.luaj.vm2.lib.jse.JsePlatform
* @see org.luaj.vm2.lib.jme.JmePlatform
*/
public static Globals standardGlobals() {
Globals globals = new Globals();
globals.load(new JseBaseLib());
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new StringLib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());
globals.load(new JseOsLib());
globals.load(new LuajavaLib());
LoadState.install(globals);
LuaC.install(globals);
return globals;
}
在创建Globals对象的同时,初始化了lua的基本功能。例如基本函数,基本库函数table等.
Globals 继承 LuaValue 对象,LuaValue对象用来表示在Lua语言的基本数据类型。比如:Nil,Number,String,Table,userdata,Function等。尤其要注意LuaValue也表示了Lua语言中的函数。所以,对于Lua语言中的函数操作都是通过LuaValue来实现的。
1- lua语言调用java方法
下面通过一个在lua中调用java的函数例子来演示,该例子来自官方。
main.lua 类:
String script = "hyperbolic.lua";
Globals globals = new Globals();
globals.load(new JseBaseLib());
globals.load(new PackageLib());
globals.load(new Bit32Lib());
globals.load(new TableLib());
globals.load(new StringLib());
globals.load(new CoroutineLib());
globals.load(new JseMathLib());
globals.load(new JseIoLib());
globals.load(new JseOsLib());
globals.load(new LuajavaLib());
//加载自定义库
globals.load(new hyperbolic());
LoadState.install(globals);
LuaC.install(globals);
LuaValue chunk = globals.loadfile(script);
chunk.call();
自定义java类,在lua中注册,并通过lua 语法来调用。
/**
* Sample library that can be called via luaj's require() implementation.
*
* This library, when loaded, creates a lua package called "hyperbolic"
* which has two functions, "sinh()" and "cosh()".
*
* Because the class is in the default Java package, it can be called using
* lua code such as:
*
<pre> {@code
* require 'hyperbolic'
* print('sinh', hyperbolic.sinh)
* print('sinh(1.0)', hyperbolic.sinh(1.0))
* }</pre>
*
* When require() loads the code, two things happen: 1) the public constructor
* is called to construct a library instance, and 2) the instance is invoked
* as a java call with no arguments. This invocation should be used to initialize
* the library, and add any values to globals that are desired.
*/
public class hyperbolic extends TwoArgFunction {
/** Public constructor. To be loaded via require(), the library class
* must have a public constructor.
*/
public hyperbolic() {
}
/** The implementation of the TwoArgFunction interface.
* This will be called once when the library is loaded via require().
* @param modname LuaString containing the name used in the call to require().
* @param env LuaValue containing the environment for this function.
* @return Value that will be returned in the require() call. In this case,
* it is the library itself.
*/
public LuaValue call(LuaValue modname, LuaValue env) {
LuaValue library = tableOf();
library.set( "sinh", new sinh() );
library.set( "cosh", new cosh() );
env.set( "hyperbolic", library );
env.get("package").get("loaded").set("hyperbolic", library);
return library;
}
/* Each library function is coded as a specific LibFunction based on the
* arguments it expects and returns. By using OneArgFunction, rather than
* LibFunction directly, the number of arguments supplied will be coerced
* to match what the implementation expects. */
/** Mathematical sinh function provided as a OneArgFunction. */
static class sinh extends OneArgFunction {
public LuaValue call(LuaValue x) {
return LuaValue.valueOf(Math.sinh(x.checkdouble()));
}
}
/** Mathematical cosh function provided as a OneArgFunction. */
static class cosh extends OneArgFunction {
public LuaValue call(LuaValue x) {
return LuaValue.valueOf(Math.cosh(x.checkdouble()));
}
}
}
hyperbolic.lua 脚本:
require 'hyperbolic'
print('hyperbolic', hyperbolic)
print('hyperbolic.sinh', hyperbolic.sinh)
print('hyperbolic.cosh', hyperbolic.cosh)
print('sinh(0.5)', hyperbolic.sinh(0.5))
print('cosh(0.5)', hyperbolic.cosh(0.5))
上面实现了在java语言中定义的java方法可以通过lua语言调用。
2 -java语言调用lua方法
在java语言中调用lua 语言中的hi()自定义函数,并传递参数some. 在java语言中获取全局hTable函数,并迭代里面的内容。
main.java 文件代码:
Globals globals = JsePlatform.standardGlobals();
//加载lua脚本,并编译
LuaValue luachuck = globals.load(new InputStreamReader(new FileInputStream(new File("hi.lua"))), "chunkname").call();
//在Globals获取全局函数hi,并传递参数调用
LuaValue func = globals.get(LuaValue.valueOf("hi"));
//在luaj中LuaValue映射了lua中的基本数据类型,包括函数
func.invoke(new LuaValue[]{LuaValue.valueOf(new Date().toString())});
LuaValue hTable = globals.get(LuaValue.valueOf("hTable"));
//迭代table结构
LuaValue k = LuaValue.NIL;
while ( true ) {
Varargs n = hTable.next(k);
if ( (k = n.arg1()).isnil() )
break;
LuaValue v = n.arg(1);
System.out.println("v:"+v.tostring());
LuaValue m = n.arg(2);
//把lua 结构转换成java结构
LuaTable tb = (LuaTable)CoerceLuaToJava.coerce(m, LuaTable.class);
System.out.println("m:"+tb.typename());
}
hi.lua 文件代码:
function hi(some)
print("every day is a new day:"..some)
end
hTable={
[1]={"a","b","c"},
[2]={"d","e","f"}
}
3 lua调用java中的对象,以及对象属性。
main.java文件内容:
Globals globals = JsePlatform.standardGlobals();
//加载lua脚本,并编译
LuaValue luachuck = globals.load(new InputStreamReader(new FileInputStream(new File("calljava.lua"))), "chunkname").call();
HiObject.java类文件:
public class HiObject
{
public int a ;
public static int b;
public HiObject(int a)
{
this.a = a;
}
public static void staticShowHiObject()
{
System.out.println("staticShowHiObject b:"+b);
}
public void showHiObject()
{
System.out.println("showHiObject a:"+a);
}
}
calljava.lua文件:
local hiObjecClazz = luajava.bindClass("test.HiObject")
hiObjecClazz.b =666
hiObjecClazz:staticShowHiObject()
local hiObject = luajava.newInstance("test.HiObject", 888);
hiObject:showHiObject()
4 java类对象传递通过参数传递到lua语言中
main.java文件:
Globals globals = JsePlatform.standardGlobals();
//加载lua脚本,并编译
LuaValue luachuck = globals.load(new InputStreamReader(new FileInputStream(new File("calljavaobject.lua"))), "chunkname").call();
//在Globals获取全局函数hi,并传递参数调用
LuaValue func = globals.get(LuaValue.valueOf("calljavaobjectfunc"));
HiObject hiObject =new HiObject(999);
LuaValue luaObject =CoerceJavaToLua.coerce(hiObject);
func.invoke(new LuaValue[]{luaObject});
calljavaobject.lua文件:
function calljavaobjectfunc(javaobject)
javaobject:showHiObject()
end