版本: cocos2d-x
语言: C++/Java/Lua
简介
cocos2d-x原生平台Android 接入第三方SDK, 需要了解LuaJavaBridge的使用。
它封装了用于Java
和Lua
的相互调用, 其调用通过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等
- 一定要根据考虑不同版本对原生平台方法的支持,这个主要是防止后续增加的功能,前期版本调用错误
Lua
的callStaticMethod 注意第三个传入参数,一定要为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);
后续补充...