簡介:
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);