Luaj学习笔记(四) - 使用Java创建自定义Lua库
自定义库示例代码
参考GitHub上找到的示例代码,重新写了一个简单的示例小项目,话不多说上代码:
自定义库的源代码
Java文件命名:TestCustomLibrary.java
package pers.landriesnidis.testluaj.func;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.VarArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
public class MyLibrary extends TwoArgFunction{
@Override
public LuaValue call(LuaValue modname, LuaValue env) {
LuaValue library = tableOf();
library.set( "time", new TimeFunc() );
library.set( "echo", new EchoFunc() );
library.set( "max", new MaxFunc() );
library.set( "average", new AverageFunc() );
library.set( "list", new ListFunc() );
env.set( "mylib", library );
env.get("package").get("loaded").set("mylib", library);
return library;
}
/**
* 获取当前时间
* 无参数的方法
*/
static class TimeFunc extends ZeroArgFunction{
@Override
public LuaValue call() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
return LuaValue.valueOf(df.format(new Date()).toString());
}
}
/**
* 回显传入的参数
* 接收一个参数的方法
*/
static class EchoFunc extends OneArgFunction{
@Override
public LuaValue call(LuaValue arg) {
return LuaValue.valueOf("You say: " + arg.checkstring());
}
}
/**
* 比较并返回两个整数中较大的值
* 接收两个参数的方法
*/
static class MaxFunc extends TwoArgFunction{
@Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
if(arg1.checkint()>arg2.checkint()){
return arg1;
}else{
return arg2;
}
}
}
/**
* 计算三个整数的平均数
* 接收三个参数的方法
*/
static class AverageFunc extends ThreeArgFunction{
@Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
return LuaValue.valueOf((arg1.checkint() + arg2.checkint() + arg3.checkint())/3.0);
}
}
/**
* 列表显示传入的所有参数
* 接收多个参数的方法
*/
static class ListFunc extends VarArgFunction {
public Varargs invoke(Varargs args) {
int n = args.narg();
StringBuilder sb = new StringBuilder();
for(int i=1;i<=n;++i){
sb.append(String.format("第%d个数是:%d\n", i, args.checkint(i)));
}
return valueOf(sb.toString());
}
}
}
Lua脚本源代码
Lua脚本文件命名:test_custom_library.lua
require 'mylib'
print(mylib.time())
print(mylib.echo('Hello,World!'))
print(mylib.max(100,101))
print(mylib.average(1,2,3))
print(mylib.list(2,4,8,16,32,64,128,256,512,1024))
载入脚本的启动代码
Java文件命名:TestCustomLibrary.java
package pers.landriesnidis.testluaj.func;
import org.luaj.vm2.Globals;
import org.luaj.vm2.LoadState;
import org.luaj.vm2.compiler.LuaC;
import org.luaj.vm2.lib.jse.JsePlatform;
public class TestCustomLibrary {
public static void main(String[] args) {
// lua脚本文件所在路径
String luaPath = "script/test_custom_library.lua";
Globals globals = JsePlatform.standardGlobals();
//加载自定义函数库
globals.load(new MyLibrary());
LoadState.install(globals);
LuaC.install(globals);
// 加载脚本文件script/test.lua,并编译
globals.loadfile(luaPath).call();
}
}
运行结果
2018-08-22 20:45:35
You say: Hello,World!
101
2
第1个数是:2
第2个数是:4
第3个数是:8
第4个数是:16
第5个数是:32
第6个数是:64
第7个数是:128
第8个数是:256
第9个数是:512
第10个数是:1024
一些可以提供参考的资料
官方提供的示例代码
GitHub中开源的关于创建自定义Lua库的示例代码:https://github.com/luaj/luaj/blob/master/examples/jse/hyperbolic.java
LuaJ的函数库源代码
LuaJ中已经实现好的函数库的源代码是最容易获取到的示例代码:
其中最直观的莫过于MathLib.class:
public class MathLib extends TwoArgFunction {
/** Pointer to the latest MathLib instance, used only to dispatch
* math.exp to tha correct platform math library.
*/
public static MathLib MATHLIB = null;
/** Construct a MathLib, which can be initialized by calling it with a
* modname string, and a global environment table as arguments using
* {@link #call(LuaValue, LuaValue)}. */
public MathLib() {
MATHLIB = this;
}
/** Perform one-time initialization on the library by creating a table
* containing the library functions, adding that table to the supplied environment,
* adding the table to package.loaded, and returning table as the return value.
* @param modname the module name supplied if this is loaded via 'require'.
* @param env the environment to load into, typically a Globals instance.
*/
public LuaValue call(LuaValue modname, LuaValue env) {
LuaTable math = new LuaTable(0,30);
math.set("abs", new abs());
math.set("ceil", new ceil());
math.set("cos", new cos());
math.set("deg", new deg());
math.set("exp", new exp(this));
math.set("floor", new floor());
math.set("fmod", new fmod());
math.set("frexp", new frexp());
math.set("huge", LuaDouble.POSINF );
math.set("ldexp", new ldexp());
math.set("max", new max());
math.set("min", new min());
math.set("modf", new modf());
math.set("pi", Math.PI );
math.set("pow", new pow());
random r;
math.set("random", r = new random());
math.set("randomseed", new randomseed(r));
math.set("rad", new rad());
math.set("sin", new sin());
math.set("sqrt", new sqrt());
math.set("tan", new tan());
env.set("math", math);
env.get("package").get("loaded").set("math", math);
return math;
}
abstract protected static class UnaryOp extends OneArgFunction {
public LuaValue call(LuaValue arg) {
return valueOf(call(arg.checkdouble()));
}
abstract protected double call(double d);
}
abstract protected static class BinaryOp extends TwoArgFunction {
public LuaValue call(LuaValue x, LuaValue y) {
return valueOf(call(x.checkdouble(), y.checkdouble()));
}
abstract protected double call(double x, double y);
}
static final class abs extends UnaryOp { protected double call(double d) { return Math.abs(d); } }
static final class ceil extends UnaryOp { protected double call(double d) { return Math.ceil(d); } }
static final class cos extends UnaryOp { protected double call(double d) { return Math.cos(d); } }
static final class deg extends UnaryOp { protected double call(double d) { return Math.toDegrees(d); } }
static final class floor extends UnaryOp { protected double call(double d) { return Math.floor(d); } }
static final class rad extends UnaryOp { protected double call(double d) { return Math.toRadians(d); } }
static final class sin extends UnaryOp { protected double call(double d) { return Math.sin(d); } }
static final class sqrt extends UnaryOp { protected double call(double d) { return Math.sqrt(d); } }
static final class tan extends UnaryOp { protected double call(double d) { return Math.tan(d); } }
static final class exp extends UnaryOp {
final MathLib mathlib;
exp(MathLib mathlib) {
this.mathlib = mathlib;
}
protected double call(double d) {
return mathlib.dpow_lib(Math.E,d);
}
}
/*
省略余下代码……
*/
}