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); 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM