如何在Java中使用Lua脚本语言

移动开发 iOS
如何在Java中使用Lua脚本语言是本文要介绍的内容,主要是来学习LUA脚本语言在JAVA中如何来使用,Lua就不说了, 现在比较热门,

如何在Java中使用Lua脚本语言是本文要介绍的内容,主要是来学习LUA脚本语言JAVA中如何来使用,Lua就不说了, 现在比较热门, 语法也很简单. 为了在Java中调用, 折腾了比较长的时间, 就把一些东西记在下面.来看详细内容讲解。

Lua是支持内嵌在C程序中的, 但是官方不支持Java. 在网上查了下, 有LuaJava开源库, 拿来试用了一下, 发现这个库还算比较完善的. 地址是

http://www.keplerproject.org/luajava/ 
  • 1.

这个LuaJava实际上就是按照Lua官方文档, 把Lua的C接口通过JNI包装成Java的库. 下载, 里面是一个.dll, 一个.jar. 把.dll放到java.library.path下, 再把.lib放到classpath中, helloworld运行OK.

但是, 测试的时候, 很快发现了第一个问题: 在调用LuaJava中提供的LuaState.pushInteger 方法的时候, 出现了错误 : Unsatisfied Link Error. 其他的LuaState.pushNumber方法倒是没有问题. 用Depends工具看了下, 这个.dll居然没有导出pushInteger这个函数. 晕....

下载LuaJava的源代码, 查看了下Luajava.c 和 Luajava.h, 发现果然里面有点问题, 在.h里面定义了JNI中对应Java函数的C函数

JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushInteger

但是.c中没有实现这个函数. 无语, 看来大马虎哪都有啊. 幸亏有源代码, 照猫画虎在Luajava.c中加上这个函数的实现,

JNIEXPORT void JNICALL Java_org_keplerproject_luajava_LuaState__1pushInteger  
   (JNIEnv * env, jobject jobj, jobject cptr, jint i)  
{  
    lua_State * L = getStateFromCPtr( env , cptr );  
    lua_pushinteger(L, i);  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

然后编译. 编译也出现了问题了, 官方文档中说可以用VC++来Build, 但是没有说官方用的是什么版本. 我用VC2005就不行. 好在Luajava比较小, 就一个.h 一个 .c , 在VC中新建一个.dll项目, 把文件加进去, 修改一下build参数 (Include 需要加上lua的头文件, lib中需要加上lua的.lib文件, 另外要选上 Compile as C Code (/TC) ) Build, 通过了.

这时再在Java中调用pushInteger方法就没有问题了.

在测试中, 发现Luajava提供的文档中, 对于Lua脚本怎么调用Java对象/方法很详细, 但是在Java中怎么调用Lua函数/取得返回值 就没有. 参考了http://www.lua.org/manual/5.1/manual.html#lua_CFunction 的Lua C文档, 实现了传递对象到Lua中并取得返回值的代码:

Test1: 测试传递简单类型, 并取得返回值:

Lua 脚本(test.lua):

function test(a,b)  
    return a+b  
end 
  • 1.
  • 2.
  • 3.

Java代码:

static {  
        //加载Lua5.1.dll, 因为LuaJava最后还是要调用Lua的东西  
        System.loadLibrary("lua5.1");  
    }  
      
    public static void main(String[] argu) throws LuaException {  
          
        LuaState L = LuaStateFactory.newLuaState();  
 
        L.openLibs();  
 
        //读入Lua脚本  
        int error = L.LdoFile("test.lua");  
        if (error != 0) {  
            System.out.println("Read/Parse lua file error. Exit.");  
            return;  
        }   
          
        //找到函数test  
        L.getField(LuaState.LUA_GLOBALSINDEX, "test");  
        //参数1压栈  
        L.pushInteger(1);  
        //参数2压栈  
        L.pushInteger(2);  
        //调用!! 一共两个参数, 1个返回值  
        L.call(2, 1);  
        //保存返回值, 到a中  
        L.setField(LuaState.LUA_GLOBALSINDEX, "a");  
        //读入a  
        LuaObject l = L.getLuaObject("a");  
        //打印结果.  
        System.out.println("Result is " + l.getString());  
        L.close();  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.

测试2: 传递Java对象

class Value {  
    public int i;  
    public void inc() {  
        i++;  
    }  
    public int get() {  
        return i;  
    }  
    public String toString() {  
        return "Value is " + i;  
    }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

Lua脚本: (该脚本中调用两次对象的inc方法, 并调用get方法输出结果)

function test1(v)  
    v:inc();  
    v:inc();  
    print("In lua: " .. v:get());  
    return v  
end 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

Java 代码: (前面都一样, 略)

//找到函数test1  
L.getField(LuaState.LUA_GLOBALSINDEX, "test1");  
//生成新的对象供测试  
Value v = new Value();  
//对象压栈  
L.pushObjectValue(v);  
//调用函数test1, 此时1个参数, 1个返回值  
L.call(1, 1);  
//结果放在b中.  
L.setField(LuaState.LUA_GLOBALSINDEX, "b");  
LuaObject l = L.getLuaObject("b");  
System.out.println("Result is " + l.getObject()); 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

运行结果:

Result is Value is 2  
In lua: 2 
  • 1.
  • 2.

和预期的一致.

实现一个怪物的创建,把lua里的设定当作初始状态传给monstor,名字为sample monstor,防御10,攻击10,生命100

1.先导入lib--luajava-1.1.jar

import org.keplerproject.luajava.LuaState;  
import org.keplerproject.luajava.LuaStateFactory;  
 
public class Load{  
LuaState luaState;  
/**  
* Constructor  
* @param fileName File name with Lua .  
*/  
Load(final String fileName) {  
this.luaState = LuaStateFactory.newLuaState();  
 
this.luaState.openLibs();  
   this.luaState.LdoFile(fileName);  
 
}  
/**  
* Ends the use of Lua environment.  
*/  
void close() {  
this.luaState.close();  
}  
/**  
* Call a Lua inside the Lua to insert  
* data into a Java object passed as parameter  
* @param Name Name of Lua .  
* @param obj A Java object.  
*/  
void run(String Name, Object obj) {  
this.luaState.getGlobal(Name);  
this.luaState.pushJavaObject(obj);  
this.luaState.call(1,0);  
}  
}  
 
public class Monster{  
/* Info */  
protected String race;  
protected int defense;  
protected int attack;  
protected int life;  
/* */  
private Load ;  
public Monster(String race) {  
/* Loads Lua for this race.*/  
this. = new Load(race+".lua");  
/*Call Lua create .*/  
.run("create", this);  
}  
 
public void setRace(String race) {  
   this.race = race;  
}  
public String getRace() {  
return race;  
}  
public int getDefense() {  
return this.defense;  
}  
public void setDefense(int defense) {  
this.defense = defense;  
}  
public int getLife() {  
return this.life;  
}  
public void setLife(int life) {  
this.life = life;  
}  
public void setAttack(int attack) {  
this.attack = attack;  
}  
public int getAttack() {  
return this.attack;  
}  
}  
 
monstor.lua---  
 
create(monster)  
monster:setRace("Sample Monster")  
monster:setDefense(10)  
monster:setAttack(10)  
monster:setLife(100)  
end 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.

但总是抛出这个错误:

PANIC: unprotected error in call to Lua API (Invalid method call. No such method.) 
  • 1.

不知为何,以后用到的时候再research.

已经查出来,原来在Monster类中少了个方法:

public void setRace(String race) {  
   this.race = race;  

  • 1.
  • 2.
  • 3.

怪不得会找不到,

要在一lua文件a.lua里导入其他的lua文件b.lua,用require "b"

如果要从lua中运算后得到返回参数,则需要做一下修改:在lua文件中改成:

create(monster)  
monster:setRace("Sample Monster")  
monster:setDefense(10)  
monster:setAttack(10)  
monster:setLife(100)  
return monster  
end 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

在Load.java中的run改成如下:

void run(String Name, Object obj) {  
   this.luaState.getGlobal(Name);  
   this.luaState.pushJavaObject(obj);  
   this.luaState.call(1, 1);// 一个参数,0个返回   
   try {  
    Object object =luaState.getObjectFromUserdata(1);  
   } catch (LuaException e) {  
    e.printStackTrace();  
   }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

小结:如何在Java中使用Lua脚本语言的内容介绍完了,希望通过本文的学习能对你有所帮助!

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-08-23 09:56:52

UnicodeLua

2011-08-23 09:44:28

LUA脚本

2011-08-25 13:22:40

CEGUILua脚本

2011-09-07 09:51:27

Javascript

2010-07-01 09:29:15

Java脚本语言javax.scrip

2011-08-22 18:00:53

Lua语言

2011-08-22 16:59:28

Lua

2011-08-25 11:02:04

2011-08-25 10:40:21

Lua游戏

2011-08-22 17:41:23

LUA 脚本 语言

2011-08-22 18:08:09

Lua脚本

2011-08-24 13:32:17

2011-06-22 14:07:42

Lua

2022-11-23 08:14:42

bash 脚本test 命令

2011-08-25 14:26:40

LUA数据文件

2010-02-26 13:03:31

Python脚本语言

2021-03-14 09:28:24

Linux Shell脚本

2022-10-09 10:18:44

LinuxShell脚本

2022-12-22 20:47:01

脚本循环结构

2021-09-10 10:30:22

Java代码
点赞
收藏

51CTO技术栈公众号