Java与Lua互相调用

/ luaJava / 没有评论 / 2294浏览

Java与Lua互相调用

前言:

Lua是一种小巧的脚本语言,如今常用于游戏开发,特别是客户端开发,基本上都是基于Lua来实现热更新,在Unity开发中更有uLua(最新版改名为toLua)这样成熟的热更框架。这里我设想用Lua+Java来实现服务器的热更,不成熟的想法,这里想尝试一下LuaJava如何互相调用。

插件选择:

假如引入第三方库,可以找到比较常用的两个选择:LuaJavaLuaJ,简单做一下对比:

第三方库实现特性
LuaJava非纯Java实现,需要通过native方法调用C库,依赖于Lua 5.1会导致JVM崩溃,不再更新,没人维护
LuaJ(LuaJavaBridge)纯Java实现的Lua解析器,无需使用native不会因错误导致JVM crash,支持JSR-223

LuaJava简介

Lua是支持内嵌在C程序中的,但是官方不支持Java,所以我们只能寻找第三方插件了,找到了一个LuaJava,这是一个开源项目,实现方式:LuaJava实际上就是按照Lua官方文档,把Lua的C接口通过JNI包装成Java的库。下载资源,里面是一个.dll和 一个.jar。把.dll放到java.library.path下,再把.lib放到classpath中。

LuaJ简介

主要特征

LuaJ核心原理

LuaJ的核心其实就是:从Lua调用Java和从Java调用Lua。经过上述对比,最终我还是选择纯Java实现,且仍然有人维护更新的LuaJ解析器,而且它也支持LuaJava API


LuaJ的下载使用:

下载:

<!-- https://mvnrepository.com/artifact/org.luaj/luaj-jse -->
<dependency>
    <groupId>org.luaj</groupId>
    <artifactId>luaj-jse</artifactId>
    <version>3.0.1</version>
</dependency>

实战

在Java中调用Lua

String luaStr = "print 'hello,world!'";
Globals globals = JsePlatform.standardGlobals();
LuaValue chunk = globals.load(luaStr);
chunk.call();

此处luaStr中只能放一个lua的方法,或者是一句lua语句,不可以出现多个function放在同一个String中使用此方法来调用。

--无参函数
function hello()
print 'hello'
end
--带参函数
function test(str)
print('data from java is:'..str)
return 'haha'
end
String luaPath = "res/lua/login.lua";   //lua脚本文件所在路径
Globals globals = JsePlatform.standardGlobals();
//加载脚本文件login.lua,并编译
globals.loadfile(luaPath).call();
//获取无参函数hello
LuaValue func = globals.get(LuaValue.valueOf("hello"));
//执行hello方法
func.call();
//获取带参函数test
LuaValue func1 = globals.get(LuaValue.valueOf("test"));
//执行test方法,传入String类型的参数参数
String data = func1.call(LuaValue.valueOf("I'am from Java!")).toString();
//打印lua函数回传的数据
Logger.info("data return from lua is:"+data);
hello
data from java is:I'am from Java!
四月 07, 2017 5:31:25 下午 com.tw.login.tools.Logger info
信息: lua return data:haha

在Lua中调用Java:

package com.tw.login.tools;
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
 
public class Logger {
    public static String TAG = "Logger";
    private static Log logger = LogFactory.getLog(Logger.class);;
    public Logger(){
        if(logger == null){
            logger = LogFactory.getLog(Logger.class);
        }
    }
 
    public void TestLogger(String str) {
        logger.info(str);
    }
 
    public static void info(String content){
        logger.info(content);
    }
}
--使用luajava创建java类的实例(对象)
local logger = luajava.newInstance("com.tw.login.tools.Logger")
--调用对象方法
logger:TestLogger("Test call java in lua0")
--使用luajava绑定一个java类
local logger_method = luajava.bindClass("com.tw.login.tools.Logger");
--调用类的静态方法/变量
logger_method:info("test call static java function in lua")
print(logger_method.TAG)
-- 使用绑定类创建类的实例(对象)
local logger_instance = luajava.new(logger_method)
-- 调用对象方法
logger_instance:TestLogger("Test call java in lua1")

当前我们只是实现了Lua中调用Java的逻辑,但是作为一种脚本语言,Lua没办法脱离高级语言而独立运行起来,所以要测试Lua是否能正常实现对Java的调用,还是需要在Java中运行此Lua脚本,参考之前在Java调用.lua脚本文件的方法,在Java中的main入口函数中添加一下内容:

Globals globals = JsePlatform.standardGlobals();
globals.loadfile("res/lua/test.lua").call();
四月 07, 2017 2:17:04 下午 com.tw.login.tools.Logger TestLogger
信息: Test call java in lua0
四月 07, 2017 2:17:04 下午 com.tw.login.tools.Logger info
信息: test call static java function in lua
Logger
四月 07, 2017 2:17:04 下午 com.tw.login.tools.Logger TestLogger
信息: Test call java in lua1

其他:


参考: