LuaObjcBridge 用于在 Lua 与 iOS 原生层之间传递基础类型、表和 Lua 回调。本文以 Cocos2d-x 3.x 的 Lua 绑定为例;不同引擎分支的可用类型和文件路径可能不同。
Lua 调用 Objective-C Cocos2d-x 提供 cocos.cocos2d.luaoc,核心入口为 callStaticMethod。它调用的是 Objective-C 类方法,不是任意实例方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 local luaoc = {}local callStaticMethod = LuaObjcBridge.callStaticMethodfunction luaoc.callStaticMethod (className, methodName, args) local ok, ret = callStaticMethod(className, methodName, args) if not ok then local msg = string .format ("luaoc.callStaticMethod(\"%s\", \"%s\", \"%s\") - error: [%s] " , className, methodName, tostring (args), tostring (ret)) if ret == -1 then print (msg .. "INVALID PARAMETERS" ) elseif ret == -2 then print (msg .. "CLASS NOT FOUND" ) elseif ret == -3 then print (msg .. "METHOD NOT FOUND" ) elseif ret == -4 then print (msg .. "EXCEPTION OCCURRED" ) elseif ret == -5 then print (msg .. "INVALID METHOD SIGNATURE" ) else print (msg .. "UNKNOWN" ) end end return ok, ret end return luaoc
同样的也是在OC层提供了一个LuaObjcBridge的类,注册了一个callStaticMethod的方法。
1 2 3 4 5 6 7 8 9 10 11 void LuaObjcBridge::luaopen_luaoc(lua_State *L) { s_luaState = L; lua_newtable(L); lua_pushstring(L, "callStaticMethod"); lua_pushcfunction(L, LuaObjcBridge::callObjcStaticMethod); lua_rawset(L, -3); lua_setglobal(L, "LuaObjcBridge"); }
调用与回调示例 Objective-C 类方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 无参数 + (void) CreateCamera{ NSLog(@"到iOS 平台了"); //... todo } // 一个lua委托参数 + (void) DoTakePic: (NSDictionary *)dict{ // 获取lua方法的ID int luaFunc = (int)[[dict objectForKey:@"lua_func"] intValue]; // 全局保存一份 luaCallbackFunc = luaFunc; // ...todo 拍照 //保存图片后 //[[CameraManager GetInstance] execLuaFunc]; }
Lua 调用方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 local OC_CLASSNAME = "CameraManager" function CameraUtil:CreateCamera () if device.platform == "ios" then local luaoc = require ("cocos.cocos2d.luaoc" ) luaoc.callStaticMethod(OC_CLASSNAME, "CreateCamera" , nil ) end end function CameraUtil:TakeCameraPic (saveImgCallBack) if device.platform == "ios" then local luaoc = require ("cocos.cocos2d.luaoc" ) local param = {lua_func = saveImgCallBack} luaoc.callStaticMethod(OC_CLASSNAME, "DoTakePic" , param) end end
上面的两个示例分别对应无参调用和传入 Lua 回调。原生层拿到的是函数 ID;调用结束后必须释放这个 ID,且只释放一次:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #import "cocos2d.h" #import "CCLuaEngine.h" #import "CCLuaBridge.h" // 执行lua方法 - (void) execLuaFunc{ //回调函数入栈,luaCallbackFunc就是lua传过来的委托的ID LuaBridge::pushLuaFunctionById(luaCallbackFunc); LuaStack *stack = LuaBridge::getStack(); // 参数入栈 stack->pushString("success"); //执行函数,参数个数为1 stack->executeFunction(1); // release LuaBridge::releaseLuaFunctionById(luaCallbackFunc); }
生命周期与线程注意事项
原生侧若把 luaCallbackFunc 存为全局变量,同时发起多个请求会互相覆盖。应按请求 ID 保存回调,或在发起下一次请求前拒绝旧请求。
无论成功、失败还是取消,都要在同一条完成路径调用 LuaBridge::releaseLuaFunctionById;遗漏会造成 Lua 函数引用无法释放。
从系统相机、相册等异步回调进入 Lua 时,应切换到 Cocos2d-x 可安全执行 Lua 的线程/时机,避免与渲染或 Lua 栈并发访问。
callStaticMethod 返回的 ok 必须检查;类名、方法名或参数类型不匹配时不要继续按成功结果处理。
相关阅读