赞
踩
最近要把Lua编写的优化算法集成到JavaWeb项目里,搜了一圈,大多人推荐Luaj,研究了一圈发现基本调用是可以的,但是如果lua代码中出现require其他lua文件,会提示找不到,折腾了三天,最后在一位同学的博客下找到了灵感。经过了小小的改动,原因是版本问题。
感谢:原著地址https://www.cnblogs.com/softidea/p/5285939.html这个例子中,不仅包括Java调用Lua,也包括Lua调用java
环境配置:
JDK:1.8
Lua:5.1
LuaJ :2.0.3
java:
- package org.example;
-
- import org.luaj.vm2.Globals;
- import org.luaj.vm2.LoadState;
- import org.luaj.vm2.LuaValue;
- import org.luaj.vm2.compiler.LuaC;
- import org.luaj.vm2.lib.jse.JsePlatform;
-
- /**
- * Hello world!
- *
- */
- public class App
- {
- public static void main( String[] args )
- {
- // test1();
- // test2();
- // test3();
- // test4();
- long key = getKey();
- System.out.println(key);
- System.out.println(getKeyJava());
- }
-
- public static long getKey() {
- //获取一个lua的运行环境,lua虚拟机应该就在这里了
- //lua是个弱类型语言,在java里,所有从lua获得的,或者要传递给lua的,都是LuaValue对象
- LuaValue _G = JsePlatform.standardGlobals();
- //执行gen.lua脚本
- //_G.get("dofile")获取dofile方法的对象
- //get其实是获取table值的方法,dofile就是全局table的一个值
- //对于Function类型的对象可以用call方法去调用,参数就是lua方法需要的参数,但是一定要转换成LuaValue类型
- _G.get("dofile").call(LuaValue.valueOf("D:\\LuaJTest\\src\\main\\java\\org\\example\\gen.lua"));
- //上一句执行完以后,gen.lua中的genkey函数就在全局变量中了,
- //可以这样直接调用
- LuaValue key = _G.get("genkey").call();
- return key.checklong();
- }
- //用java实现的,比较用
- //value = (int)(timestamp / 1000 ) ^ (int)(timestamp / 400)
- public static long getKeyJava() {
- long tm = System.currentTimeMillis() / 1000;
- return (tm / 1000) ^ (tm / 400);
- }
-
-
- private static void test4() {
- // lua脚本文件所在路径
- String luaPath = "D:\\LuaJTest\\src\\main\\java\\org\\example\\test3.lua";
- Globals globals = JsePlatform.standardGlobals();
- // 加载脚本文件script/test.lua,并编译
- globals.loadfile(luaPath).call();
-
- // 获取函数:pi()
- LuaValue func = globals.get(LuaValue.valueOf("pi"));
- // 执行pi()方法获取圆周率
- double pi = func.call().todouble();
- System.out.println("圆周率:" + pi);
- }
-
- private static void test3() {
- String luaPath = "D:\\LuaJTest\\src\\main\\java\\org\\example\\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();
- }
-
- private static void test2() {
- // lua脚本文件所在路径
- String luaPath = "D:\\LuaJTest\\src\\main\\java\\org\\example\\test.lua";
- Globals globals = JsePlatform.standardGlobals();
- // 加载脚本文件script/test.lua,并编译
- globals.loadfile(luaPath).call();
-
- // 获取函数:pi()
- LuaValue func = globals.get(LuaValue.valueOf("pi"));
- // 执行pi()方法获取圆周率
- double pi = func.call().todouble();
- System.out.println("圆周率:" + pi);
-
- // 获取带参函数circle_area()
- LuaValue func1 = globals.get(LuaValue.valueOf("circle_area"));
- // 执行circle_area方法,传入double类型的半径参数
- double area = func1.call(LuaValue.valueOf(3.0)).todouble();
- // 打印lua函数回传的数据
- System.out.println("半径为3.0的圆形面积为:" + area);
- }
-
- private static void test1() {
- String luaStr = "print 'Hello World!'";
- Globals globals = JsePlatform.standardGlobals();
- LuaValue lv = globals.load(luaStr);
- lv.call();
- }
- }
- package org.example;
-
- import org.luaj.vm2.LuaValue;
- import org.luaj.vm2.lib.OneArgFunction;
- import org.luaj.vm2.lib.TwoArgFunction;
- import org.luaj.vm2.lib.ZeroArgFunction;
-
- public class Math extends OneArgFunction {
- //lua的方法都是闭包,在java中一定是用类对象与之对应的。
- //于是call这个方法就是调用闭包使用所调用的方法,必须实现
- public LuaValue call(LuaValue modname) {
- //这是类在lua里是一个模块,也就是个函数包,在lua里也就是一个table
- //table的每一个元素是一个函数(闭包而已)
- //这个lib就是一个table,用来存放各个lua模块方法
- LuaValue lib = tableOf();
- //设置timestamp方法
- lib.set("timestamp", new lua_timestamp());
- //设置异或方法
- lib.set("bitxor", new lua_bitxor());
- //这里不确定:env是该类的环境参数,暂时没研究这一句的作用,本例中不设置也没关系
- // env.set(modname.checkjstring(), lib);
- return lib;
- }
-
- static class lua_timestamp extends ZeroArgFunction {
- public LuaValue call() {
- return LuaValue.valueOf(System.currentTimeMillis() / 1000);
- }
- }
- static class lua_bitxor extends TwoArgFunction {
- public LuaValue call(LuaValue a, LuaValue b) {
- //lua传进来参数都是LuaValue的,java使用的时候需要使用相应的check方法转为本地变量
- long pa = a.checklong();
- long pb = b.checklong();
- long r = pa ^ pb;
- //返回的时候需要用valueOf方法转为LuaValue类型
- return LuaValue.valueOf(r);
- }
- }
- }
Lua:
- ---
- --- Generated by EmmyLua(https://github.com/EmmyLua)
- --- Created by a1599.
- --- DateTime: 2021/10/31 15:18
- ---
- --注意查找目录是从工程的根目录开始的
- require ("D:\\LuaJTest\\src\\main\\java\\org\\example\\div")
- --引用java提供的方法,则直接写java的类名就好
- jlib = require ("org.example.Math")
- -- 模板方法
- function genkey()
- tm = jlib.timestamp()
- a = div(tm, 1000)
- b = div(tm, 400)
- r = jlib.bitxor(a, b)
- return r
- end
- --module(..., package.seeall)
- -- 这里也可以require java提供的模块,本例没用到
- function div(a, b)
- return math.floor(a / b)
- end
重点来了!!!
在被require的lua文件中,不需要
module(..., package.seeall)
在gen.lua中require一定要全路径,并且不带后缀(.lua)。用跟目录IDE也会显示正确,但是会加载不到
require ("D:\\LuaJTest\\src\\main\\java\\org\\example\\div")
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。