cocos Lua与Java交互
简介:
cocos2d为了使Android SDK的接入,封装了LuaJavaBridge用于Java和Lua的相互调用。LuaJavaBridge从本质上来说,是通过C++作为中介,其调用流程为:
Lua调用Java: Lua -> C++ -> Java
Java调用Lua: Java -> C++ -> Lua
lua调用java
在cocos/cocos2d/luaj.lua文件下,lua调用java的方法接口:luaj.callStaticMethod
local luaj = {} local callJavaStaticMethod = LuaJavaBridge.callStaticMethod local function checkArguments(args, sig) if type(args) ~= "table" then args = {} end if sig then return args, sig end -- Java支持Lua的几种参数类型number,boolean,string, function sig = {"("} for i, v in ipairs(args) do local t = type(v) if t == "number" then sig[#sig + 1] = "F" elseif t == "boolean" then sig[#sig + 1] = "Z" elseif t == "function" then sig[#sig + 1] = "I" else sig[#sig + 1] = "Ljava/lang/String;" end end sig[#sig + 1] = ")V" return args, table.concat(sig) end --[[ @function: 调用java的接口,注意在使用的时候一定要判定是否为为Android平台 @param: className Java完整的类名 @param: methodName Java类方法名 @param: args lua传入的参数,要为table类型,否则会被转换{} @param: sig 类型简写名,格式为:(参数简写)返回类型简写 ]] function luaj.callStaticMethod(className, methodName, args, sig) -- 检测参数args并将其转换为类型简写 local args, sig = checkArguments(args, sig) return callJavaStaticMethod(className, methodName, args, sig)end return luaj
虽然在lua脚本中我们可能已添加了相关注释,但是还是再补充说明下:
1. lua调用java的类方法,其中java方法一定要为static类型
2. lua调用Java的方法一定要判定是否为Android平台,若在游戏中也要判定当前游戏的基础版本是否支持调用该SDK
-- 判定是否为android平台 -- 第一种方法 local targetPlatform = cc.Application:getInstance():getTargetPlatform() if (cc.PLATFORM_OS_ANDROID == targetPlatform) then -- do something end -- 第二种方法(推荐) if device.platform == "android" then -- do something end
3. 使用luaj.callStaticMethod时,注意第三个参数args一定要为table类型,否则将被转换{},导致错误
4. 通过checkArguments的循环我们可以看到Java支持的几种lua参数或返回值类型简写,如下:
Lua类型 | Lua简写 | 说明 |
number | F | 浮点类型 |
boolean | Z | 布尔类型 |
function | I | 整数或Lua function |
string |
Ljava/lang/String;
|
字符串 |
V
|
用于java方法中无返回值 |
此处其实跟C++调用java时,设置其参数类型简写非常类似,但是lua没有C++那么多的数据类型支持,比如:char, shot, long, double等。
5. 关于类型简写,格式为:(参数类型简写)返回类型简写
我们简单的举一些例子,方便大家理解:
lua调用java方法 | 类型简写 | 说明 |
void showText() | "()V" | 无参数,无返回 |
int getWifiLevel() | "()I" | 无参数,返回为整型 |
String getSystemVersion() | "()Ljava/lang/String;" | 无参数,返回字符串 |
int addNumber(final int num1, final int num2) | "(II)I" | 参数为两个整型,返回值为整型 |
boolean isGetPhoneData(final String name, final int Count) | "(Ljava/lang/String;I)Z" | 参数分别为字符串,整型,返回布尔类型 |
6. 调用接口有两个返回值,假设以ok,result命名:
若成功,ok为true, result若无返回值,则返回0,若有返回值,则返回;
若失败,ok为false,result为错误代码,其对应的有:
C++枚举类型 | 索引值 | 说明 |
kLuaBridgeErrorOk | 0 | 成功 |
kLuaBridgeErrorInvalidParameters | -1 | 无效的参数 |
kLuaBridgeErrorClassNotFound | -2 | java类没找到 |
kLuaBridgeErrorMethodNotFound | -3 | java类方法没找到 |
kLuaBridgeErrorExceptionOccurred | -4 | 方法执行时异常发生 |
kLuaBridgeErrorMethodSignature | -5 | 无效的类型简写 |
kLuaBridgeErrorJavaVMError | -6 | Java 虚拟机错误 |
拓展下,此处的返回错误码与关于lua与Object-C交互下的luaoc.callStaticMethod返回的错误码是一致的。
接下来我们看下cocos2d-Lua的官方示例,并简单介绍Java调用Lua的相关接口:
-- LuaBridgeTest.lua 示例仅摘抄了其主体代码 function newLuaJavaBridge() local targetPlatform = cc.Application:getInstance():getTargetPlatform() if (cc.PLATFORM_OS_ANDROID ~= targetPlatform) then return end -- 用于Lua调用Java local luaj = require "cocos.cocos2d.luaj" -- 引用库文件 local className = "com/cocos2dx/sample/LuaJavaBridgeTest/LuaJavaBridgeTest" -- java类名 local methodName = "addTwoNumbers" -- java类方法名 local args = {2 , 3} -- 参数 local sigs = "(II)I" -- 类型简写 local ok,ret = luaj.callStaticMethod(className, methodName, args, sigs) if not ok then print("luaj error:", ret) else print("The ret is:", ret) end -- 用于Java调用Lua local function callbackLua(param) if "success" == param then print("java call back success") end end args = { "callbacklua", callbackLua } sigs = "(Ljava/lang/String;I)V" ok = luaj.callStaticMethod(className,"callbackLua",args,sigs) if not ok then print("call callback error") end end
package com.cocos2dx.sample.LuaJavaBridgeTest; // 用于java调用Lua import org.cocos2dx.lib.Cocos2dxLuaJavaBridge; public class LuaJavaBridgeTest { // Lua调用java public static int addTwoNumbers(final int num1,final int num2){ return num1 + num2; } // Java调用Lua public static void callbackLua(final String tipInfo,final int luaFunc){ // 调用局部Lua-Function,将luaFunc结果发送给Lua Cocos2dxLuaJavaBridge.callLuaFunctionWithString(luaFunc, "success"); Cocos2dxLuaJavaBridge.releaseLuaFunction(luaFunc); } }
Java调用Lua
在接入支付SDK的时候,其操作是异步的,在支付结束后后,Java需要通知Lua。因为若在Java调用Lua要添加引用:
import org.cocos2dx.lib.Cocos2dxLuaJavaBridge;
其主要接口有:
// 调用局部Lua-Function public static native int callLuaFunctionWithString(int luaFunctionId, String value); // 调用全局Lua-Function public static native int callLuaGlobalFunctionWithString(String luaFunctionName, String value); // retain一次Lua-Function public static native int retainLuaFunction(int luaFunctionId); // release掉Lua-Function public static native int releaseLuaFunction(int luaFunctionId);