zoukankan      html  css  js  c++  java
  • 在Java中使用Lua脚本语言

    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 {
            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 代码: (前面都一样, 略)
            //找到函数est1
            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
     
    和预期的一致.
  • 相关阅读:
    分布式共识协议RAFT基本原理
    slave_net_timeout, MASTER_HEARTBEAT_PERIOD, MASTER_CONNECT_RETRY,以及 MASTER_RETRY_COUNT设置和查看
    单例模式
    截取字符串Java
    Hibernate+struts+JqueryAjax+jSON实现无刷新三级联动
    数组集合区别
    Android Activity生命周期(图文)!
    Activity的生命周期
    Android四大组件
    各种时间获取 .net
  • 原文地址:https://www.cnblogs.com/blogyuan/p/3739665.html
Copyright © 2011-2022 走看看