分享

在Java中使用Lua脚本语言

 quasiceo 2015-01-14

Lua就不说了, 现在比较热门, 语法也很简单. 为了在Java中调用, 折腾了比较长的时间, 就把一些东西记在下面.

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

http://www./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./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 {
       
        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();
}

测试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");
        //生成新的对象供测试
        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());


运行结果:

Result is Value is 2
In lua: 2


和预期的一致.

分享到:
评论
7 楼 屌丝的未来在哪里 2014-08-13   引用
尝试将一个java中的List对象传递给Lua进行操作,发现性能不行啊,一个size为300的list,遍历一遍并进行三两行简单的操作,要60多毫秒,同样的操作如果用java代码不到1ms,请问遇到过类似问题吗,瓶颈是在什么地方呢?
6 楼 yellfly 2012-07-20   引用
wxw3130056tom.com 写道
我下载的源码中没有 luajava.h 文件:麻烦兄弟给发一份:
我的邮箱:wangxinwei@into4g.com


博主用的可能是不同的源代码版本,我发现从LuaForge上和github上下的源代码大小是不一样的,虽然都是1.1。
我下的版本也没有luajava.h,但实际上这个文件没有什么用,因为不需要在其它C语言源代码中包含。但因缺少jni.h编译会报错,修正办法是将#include "luajava.h" 改成 #include <jni.h>。
5 楼 wxw3130056tom.com 2011-10-21   引用
我下载的源码中没有 luajava.h 文件:麻烦兄弟给发一份:
我的邮箱:wangxinwei@into4g.com
4 楼 guobosheng 2010-06-23   引用
关于重新编译的问题:我下载的LuaJava的源代码没有头文件 Luajava.h
楼主能否给我发一个Luajava.h文件,或者编译好的dll文件?谢谢!287352794g@qq.com
3 楼 guobosheng 2010-06-23   引用
关于重新编译的问题:我下载的LuaJava的源代码没有头文件 Luajava.h
2 楼 guobosheng 2010-06-23   引用
上面的问题通过修改PATH变量来达到设置java.library.path属性的目的(改变之后Eclipse需要重新启动)
参考:http://dongjiliwu./blog/421726
1 楼 guobosheng 2010-06-23   引用
楼主你好,你代码中的
static {
    //加载Lua5.1.dll, 因为LuaJava最后还是要调用Lua的东西
    System.loadLibrary("lua5.1");
}

要加载Lua5.1.dll之前要做些什么准备?

我运行你的代码出错:no lua5.1.dll in java.library.path ,望指教!

详细:
java.lang.UnsatisfiedLinkError: no lua5.1.dll in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1709)
at java.lang.Runtime.loadLibrary0(Runtime.java:823)
at java.lang.System.loadLibrary(System.java:1028)
at Hello.<clinit>(Hello.java:19)
Exception in thread "main"

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多