lua5.1网上的扩展模块很多,但是支持最新版lua却很少,主要是lua新版和旧版有兼容性问题,其实稍微修改下就能升级了
比如常用的 AndroLua , luajava , lfs , luacurl , 更多

模块兼容主要采取2种方式:

1,修改lua源码在luaconf.h定义宏LUA_COMPAT_5_1 LUA_COMPAT_5_2,以便兼容以前的模块(最方便)

缺点要重新编译lua引擎

2,修改模块源码

以下以升级luajava为例

直接编译luajava出现

  1. src\c\luajava.c(2254) : warning C4047: “初始化”:“lua_State *”与“int”的间接级别不同
  2. src\c\luajava.c(3258) : warning C4047: “函数”:“lua_State *”与“jint”的间接级别不同
  3. src\c\luajava.c(3258) : warning C4024: lua_resume”: 形参和实参 2 的类型不同
  4. src\c\luajava.c(3258) : error C2198: lua_resume”: 用于调用的参数太少
  5. src\c\luajava.c(3863) : warning C4047: “初始化”:“const char *”与“int”的间接级别不同

我们先看看2254这行是什么代码

lua_State * L = lua_open();

查看lua5.3在线文档发现根本没这个函数,按照功能对应的是luaL_newstate,把这行修改为

 lua_State * L = luaL_newstate();

接着看3258错误还挺多的

return ( jint ) lua_resume( L , nArgs );

发现lua_resume在lua5.3版本的多了一个参数,我们这传NULL

 return ( jint ) lua_resume( L , NULL , nArgs);

最后看看3863行,什么鬼
luaL_findtable什么函数,在线文档5.1,5.2,5.3都没这个函数说明,可能这个函数已经抛弃,我们先返回NULL,编译通过再说

JNIEXPORT jstring JNICALL Java_org_keplerproject_luajava_LuaState__1LfindTable
  (JNIEnv * env , jobject jobj , jobject cptr , jint idx , jstring fname , jint szhint)
{
   // lua_State * L   = getStateFromCPtr( env , cptr );
   // const char * name = ( *env )->GetStringUTFChars( env , fname , NULL );

   // const char * sub = luaL_findtable( L , ( int ) idx , name , ( int ) szhint );

   // ( *env )->ReleaseStringUTFChars( env , fname , name );

   // return ( *env )->NewStringUTF( env , sub );
   return NULL;
}

修改后编译发现有链接错误

luajava.obj : error LNK2019: 无法解析的外部符号 _lua_getfenv,该符号在函数 _Java_org_keplerproject_luajava_LuaState__1ge
tFEnv@16 中被引用
luajava.obj : error LNK2019: 无法解析的外部符号 _lua_setfenv,该符号在函数 _Java_org_keplerproject_luajava_LuaState__1se
tFEnv@16 中被引用
luajava.obj : error LNK2019: 无法解析的外部符号 _lua_getgccount,该符号在函数 _Java_org_keplerproject_luajava_LuaState__
1getGcCount@12 中被引用
luajava.obj : error LNK2019: 无法解析的外部符号 _luaL_typerror,该符号在函数 _Java_org_keplerproject_luajava_LuaState__1
Ltyperror@20 中被引用
luajava.obj : error LNK2019: 无法解析的外部符号 _luaL_getn,该符号在函数 _Java_org_keplerproject_luajava_LuaState__1Lget
N@16 中被引用
luajava.obj : error LNK2019: 无法解析的外部符号 _luaL_setn,该符号在函数 _Java_org_keplerproject_luajava_LuaState__1Lset
N@20 中被引用
luajava-1.1.dll : fatal error LNK1120: 6 个无法解析的外部命令

这里是直接去掉这几个函数,并在java中相应去掉对应native声明
编译通过,现在开始测试功能~

好吧,把java文件和库文件放到eclipse运行又发现问题

Can’t load IA 32-bit .dll on a AMD 64-bit platform

居然编译的是32位的,赶紧换64位

vcallvars X64
nmake -f makefile.win

崩溃了,还是不能运行

比较lua.h和LuaState.java文件中一些常量发现有些值还不一样,比如
LUA_REGISTRYINDEX 需要改成 new Integer(-1000000 - 1000),LUA_GLOBALSINDEX注释掉

运行runawttest发现awtTest.lua中居然还有loadstring函数,改成load

运行看看,终于可以啦

luajava升级过程 - 图1

这里就讲到这里,下面提供改后源码,不能确保完全改好~仅供学习

总结:

  1. java虚拟机有32位和64位之分,luajava编译的版本也有这个区分
    
  1. 源码换成NDK编译,编写相应Android.mk,能移植到安卓平台
  2. luajava主要通过lua <->C <->java,通过代理和反射的运用,使lua和java能互相操作
    
  1. 这里有个缺陷,在协程中并不能使用luajava,初步分析是由于协程是运行在另一个状态机L中的,而主线程都是通过一个主状态机L使lua和java交换数据,这里有待进一步改进,但需要对协程原理深入了解,以后再叙说,下面给个协程中不能使用java例子
function foo (a)
    --以下不能正确输出
    sys = luajava.bindClass("java.lang.System")
    print ( sys:currentTimeMillis() ,1 )
    return coroutine.yield(2*a)
end

co = coroutine.create(function (a,b)
    foo(a+1)
end)

sys = luajava.bindClass("java.lang.System")
print ( sys:currentTimeMillis() ,1 )
print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))

下载地址:

点击下载luajava64位和相关源码

https://github.com/haikejishu/LuaJava

编译dll时参考资料

Visual c + +相关宏:
https://msdn.microsoft.com/zh-cn/library/b0084kay.aspx,
lua文档:
http://www.runoob.com/manual/lua53doc/contents.html#contents