碎语闲谈 - Cocos lua 与native 的相互调用

今天闲聊一些关于lua 与 native 之间相互调用的问题

lua 调用 oc

1.你一定知道我的使用场景是接入sdk对不对,嗯,大多数,我们需要使用ios设备系统提供的一些内容
很贴心,cocos提供了一个 luaBridge

lua部分代码

1
2
3
4
local luaBridge = require("cocos/cocos2d/luaoc")
--代码部分 调用静态方法 类的名字 方法名字 传递给oc的参数(以表的形式传输,OC用字典的方式来接收)
function luaoc.callStaticMethod(className, methodName, args)

函数返回值
当成功时,第一个值为 true,第二个值是 oc 方法的返回值(如果有)。
当失败时,第一个值为 false,第二个值是错误代码。

oc 部分代码 只是lua来调用oc部分

1
2
3
4
+ (void)functionName:(NSDictionary *)dict{
NSLog(@"lua calling functionName");
NSString *param = [dict valueForKey:@"paramName"];
}

oc 部分代码 lua来调用oc部分并且需要回调部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+ (void)functionName:(NSDictionary *)dict{
NSLog(@"lua calling functionName with callBack");
//luaCallBackID 先暂时这么写 因为一般我们会需要把 luaCallBackID 存放起来,等待需要的时候进行回掉
int luaCallBackID = (int)[[dict valueForKey:@"callBack"] integerValue];
}


//执行lua回调方法
- (void)exeLuaCallback:(int)Handler callbackMsg:(NSString *)result
{
if (Handler){
cocos2d::LuaBridge::pushLuaFunctionById(Handler); //压入需要调用的方法id
cocos2d::LuaStack *stack = cocos2d::LuaBridge::getStack(); //获取lua栈
stack->pushString([result UTF8String]);//放入需要给lua的参数
stack->executeFunction(1); //执行lua 函数 ,共有1个参数
cocos2d::LuaBridge::releaseLuaFunctionById(luaCallBackID); //执行完然后销毁
}
}

lua 和 java 的相互调用

同样很贴心,我们会发现 cocos 提供了 luaBridge

1
2
3
4
5
local callJavaStaticMethod = LuaJavaBridge.callStaticMethod
// 类的名字 静态方法名字 参数 方法签名
function luaj.callStaticMethod(className, methodName, args, sig)
//调用 Java 方法时,支持 int/float/boolean/String/Lua function 五种参数类型

函数返回值
当成功时,第一个值为 true,第二个值是 Java 方法的返回值(如果有)。
当失败时,第一个值为 false,第二个值是错误代码。

"javajnitype图片"

JNI Type Signatures : JNI Type Signatures

"常见java签名图片"

Java 部分代码

1
2
3
4
5
public static boolean isWXAppInstalled() {
Log.v("AppActivity", "isWXAppInstalled");
return wxApi.isWXAppInstalled();
}

相对应 lua 部分

1
2
3
local luaBridge = require("cocos/cocos2d/luaj")
local ok, ret = luaBridge.callStaticMethod("org/cocos2dx/lua/AppActivity", "isWXAppInstalled", nil, "()Z")

lua 调用 java 并传递回调

java 代码部分

1
2
3
4
5
6
7
8
9
10
11
12
//register  authCodeScriptHandler 跟oc 一样,需要暂存
public static void registerGetAuthCodeHandler(int scriptHandler) {
Log.v("BaseAppActivity", "registerGetAuthCodeHandler" + scriptHandler);
authCodeScriptHandler = scriptHandler;
}


//等到需要进行回调lua 时候

Cocos2dxLuaJavaBridge.callLuaFunctionWithString(authCodeScriptHandler, authCode);
Cocos2dxLuaJavaBridge.releaseLuaFunction(authCodeScriptHandler);

相对应 带有回调lua 部分

1
2
3
4
5
6
7

//传递callBack handler(self,self.callFun)
local luaBridge = require("cocos/cocos2d/luaj")
luaBridge.callStaticMethod("org/cocos2dx/lua/AppActivity", "sendAuthRequest", nil, "()V")
luaBridge.callStaticMethod("org/cocos2dx/lua/AppActivity", "registerGetAuthCodeHandler", {callback}, "(I)V")


很完美?然而并没有结束!!!

cocos2d-x for Android 运行在多线程环境下,所以在 Lua 和 Java 交互时需要注意选择适当的线程。
cocos2d-x 在 Android 上以两个线程来运行,分别是负责图像渲染的 GL 线程和负责 Android 系统用户界面的 UI 线程。

在 cocos2d-x 启动后,Lua 代码将由 GL 线程调用,因此从 Lua 中调用的 Java 方法如果涉及到系统用户界面的显示、更新操作,那么就必须让这部分代码切换到 UI 线程上去运行。

反之亦然,从 Java 调用 Lua 代码时,需要让这个调用在 GL 线程上执行,否则 Lua 代码虽然执行了,但会无法更新 cocos2d-x 内部状态。

"写入正确的回调lua的方法"

这才是要注意的坑!!!