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

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

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

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

这个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);

}

然后编译. 编译也出现了问题了, 官方文档中说可以用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

Java代码:

static {

//加载Lua5.1.dll, 因为LuaJava最后还是要调用Lua的东西

System.loadLibrary("lua5.1");

}

public static void main(String[] argu) throws LuaException {

LuaStateL=LuaStateFactory.newLuaState();

L.openLibs();

//读入Lua脚本

interror=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

LuaObjectl=L.getLuaObject("a");

//打印结果.

System.out.println("Result is " + l.getString());

L.close();

}

测试2: 传递Java对象

class Value {

public int i;

public void inc() {

i++;

}

public int get() {

return i;

}

public String toString() {

return "Value is " + i;

}

}

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

function test1(v)

v:inc();

v:inc();

print("In lua: " .. v:get());

return v

end

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

//找到函数test1

L.getField(LuaState.LUA_GLOBALSINDEX, "test1");

//生成新的对象供测试

Valuev=newValue();

//对象压栈

L.pushObjectValue(v);

//调用函数test1, 此时1个参数, 1个返回值

L.call(1, 1);

//结果放在b中.

L.setField(LuaState.LUA_GLOBALSINDEX, "b");

LuaObjectl=L.getLuaObject("b");

System.out.println("Result is " + l.getObject());

运行结果:

Result is Value is 2

In lua: 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.=newLoad(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

但总是抛出这个错误:

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

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

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

public void setRace(String race) {

this.race= race;

}

怪不得会找不到,

要在一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

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

void run(String Name, Object obj) {

this.luaState.getGlobal(Name);

this.luaState.pushJavaObject(obj);

this.luaState.call(1, 1);// 一个参数,0个返回

try {

Objectobject=luaState.getObjectFromUserdata(1);

} catch (LuaException e) {

e.printStackTrace();

}

}

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

【编辑推荐】

【责任编辑:李程站 TEL:(010)68476606】

点赞 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值