cocos2d-x Android原生平台与Lua交互

版本: cocos2d-x

语言: C++/Java/Lua

简介


cocos2d-x原生平台Android 接入第三方SDK, 需要了解LuaJavaBridge的使用。

它封装了用于JavaLua的相互调用, 其调用通过C++为中介,简要的流程:

Lua调用Java: Lua -> C++ -> Java

Java调用Lua: Java -> C++ -> Lua

以此方式来实现数据的交互, 接下来我们分别说下这两块东西。

Lua调用Java


lua的接口文件主要在 cocos/cocos2d目录下,主要的文件是:

  • luaj.lua Lua调用Android平台的接口文件
  • luaoc.lua Lua调用苹果平台的接口文件

调用原生平台,使用的方法名均为: callStaticMethod

lua 复制代码
---------------- luaj.lua ----------------
-- 用于对参数转换为Java的类型简写
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
end

return luaj

使用Lua调用Java需要注意:

  • Java的方法一定要设置为static类型
  • 一定要判定平台的类型,比如Android,IOS,Mac等
  • 一定要根据考虑不同版本对原生平台方法的支持,这个主要是防止后续增加的功能,前期版本调用错误
  • LuacallStaticMethod 注意第三个传入参数,一定要为table表数据,避免错误

在Lua项目中,针对于平台的判定相关

lua 复制代码
-- 示例1
local targetPlatform = cc.Application:getInstance():getTargetPlatform()
if (cc.PLATFORM_OS_ANDROID == targetPlatform) then
    -- do something
end 
-- 示例2
if device.platform == "android" then
    -- do something
end

checkArguments

它主要用于将Lua的参数转换为Java的类型简写,以用于获取数据,如下Java支持的Lua类型简写

Lua类型 简写格式 说明
number F 浮点类型
boolean Z 布尔类型
function I 整数或方法
string Ljava/lang/String; 字符串
V 用于java方法中无返回值

这个是跟C++调用Java是类似的,但Lua没有那么多的数据类型支持,比如C++中的char, shot, long, double等。

类型简写的格式大致为: (参数类型简写)返回类型简写,简单的实例:

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" 参数分别为字符串,整型,返回布尔类型

checkArguments中存在关于类型简写的转换,但是建议了解下,以备突发情况使用。

callStaticMethod

它是Lua调用调用C++的中介接口,用于将参数相关通过C++传递给Java。它的主要实现在:

c 复制代码
// ../frameworks/cocos2d-x/cocos/scripting/lua-bindings/manual/platform/android目录下
// CCLuaJavaBridge.cpp
void LuaJavaBridge::luaopen_luaj(lua_State *L)
{
		s_luaState = L;
    lua_newtable(L);
    lua_pushstring(L, "callStaticMethod");
    lua_pushcfunction(L, LuaJavaBridge::callJavaStaticMethod);
    lua_rawset(L, -3);
    lua_setglobal(L, "LuaJavaBridge");
}

该接口在Lua中调用后主要会有两个返回值,分别是:

  • 成功标记,布尔类型;
  • 错误编码,整数类型

如果成功,则错误编码为0,否则就是其他数值,主要的错误码有:

c 复制代码
// CCLuaBridget.h
typedef enum {
  	// 成功
    kLuaBridgeErrorOk                   = 0, 
  	// 无效的参数
    kLuaBridgeErrorInvalidParameters    = -1,
  	// 类没有找到
    kLuaBridgeErrorClassNotFound        = -2,
  	// 方法没有找到
    kLuaBridgeErrorMethodNotFound       = -3,
    // 执行异常
    kLuaBridgeErrorExceptionOccurred    = -4,
  	// 错误的类型简写
    kLuaBridgeErrorMethodSignature      = -5,
    // 虚拟机错误
    kLuaBridgeErrorJavaVMError          = -6,
} LuaBridgeError;

这个错误类型与luaoc.lua的检测类型参数是相似的。官方实例:

  • Lua相关
lua 复制代码
-- LuaBridgeTest.lua 示例仅摘抄了其主体代码
function newLuaJavaBridge()
  local targetPlatform = cc.Application:getInstance():getTargetPlatform()
  if (cc.PLATFORM_OS_ANDROID ~= targetPlatform) then
    return 
  end 

  -- 引用库文件
  local luaj = require "cocos.cocos2d.luaj"
  -- Java类名
  local className = "com/cocos2dx/sample/LuaJavaBridgeTest/LuaJavaBridgeTest"
  -- Java方法名
  local methodName = "addTwoNumbers"  
  -- 参数
  local args = {2, 3}
  -- 类型简写
  local sigs = "(II)I"

  -- 调用方式一: 传入两个参数获取数值
  local success, result = luaj.callStaticMethod(className, methodName, args, sigs)
  if not success then
    print("luaj error:", result)
  else
    print("The result is:", result)
  end

  -- 调用方式二: 传入两个参数获取结果通过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
  • Java相关
java 复制代码
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);
  }
}

至此,Lua调用Java告一段落。

Java调用Lua

Java是允许调用Lua的,同Java调用C++一样。主要的接口是:

java 复制代码
// 调用局部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); 

后续补充...

相关推荐
大飞pkz15 小时前
【Lua】题目小练3
开发语言·lua·题目小练
遇见火星2 天前
nginx安装配置Lua模块的支持
运维·nginx·lua
慢慢沉6 天前
Lua(数据库访问)
开发语言·数据库·lua
慢慢沉6 天前
Lua协同程序(coroutine)
lua
慢慢沉6 天前
Lua元表(Metatable)
lua
慢慢沉7 天前
Lua(字符串)
开发语言·lua
慢慢沉7 天前
Lua(数组)
开发语言·lua
慢慢沉7 天前
Lua(迭代器)
开发语言·lua
慢慢沉7 天前
Lua基本语法
开发语言·lua
Feng.Lee7 天前
接口测试Postman工具高级使用技巧
功能测试·测试工具·lua·postman·可用性测试