CCLuaObjcBridge是cocos2d-x系列引擎与Objective-C进行交互的“桥梁”,老廖的quick-cocos2d-x在其framework进行了简单了封装,封装到了luaoc类中,大体可以看成:
luaoc.callStaticMethod = CCLuaObjcBridge.callStaticMethod函数原型如下:
--[[ 调用Objective-C中的静态方法 @param string className 类名 @param string methodName 方法名 @param table args 参数 ]] function luaoc.callStaticMethod(className, methodName, args) end
假定有以下Objective-C静态方法:
#import <Foundation/Foundation.h> @interface SdkApi : NSObject + (void)init:(NSDictionary*)dict; @end当尝试用以下参数调用时,会报“invalid key to 'next'“错:
luaoc.callStaticMethod("SdkApi", "init", {"platform", true})很奇怪的错误,一步一步调试,进到CCLuaObjcBridge.mm,定位到lua_next行代码:
if (hasArguments) { NSMutableDictionary *dict = [NSMutableDictionary dictionary]; lua_pushnil(L); while (lua_next(L, -2)) { NSString *key = [NSString stringWithCString:lua_tostring(L, -2) encoding:NSUTF8StringEncoding]; switch (lua_type(L, -1)) { case LUA_TNUMBER: [dict setObject:[NSNumber numberWithFloat:lua_tonumber(L, -1)] forKey:key]; break; case LUA_TBOOLEAN: [dict setObject:[NSNumber numberWithBool:lua_toboolean(L, -1)] forKey:key]; break; case LUA_TSTRING: [dict setObject:[NSString stringWithCString:lua_tostring(L, -1) encoding:NSUTF8StringEncoding] forKey:key]; break; case LUA_TFUNCTION: int functionId = retainLuaFunction(L, -1, NULL); [dict setObject:[NSNumber numberWithInt:functionId] forKey:key]; break; } lua_pop(L, 1); } [invocation setArgument:&dict atIndex:2]; [invocation invoke]; } else { [invocation invoke]; }粗略阅读了一下代码,没有发现什么异常,于是去查官方文档,终于有了发现:
int lua_next (lua_State *L, int index); Pops a key from the stack, and pushes a key–value pair from the table at the given index (the "next" pair after the given key). If there are no more elements in the table, then lua_next returns 0 (and pushes nothing). A typical traversal looks like this: /* table is in the stack at index 't' */ lua_pushnil(L); /* first key */ while (lua_next(L, t) != 0) { /* uses 'key' (at index -2) and 'value' (at index -1) */ printf("%s - %s\n", lua_typename(L, lua_type(L, -2)), lua_typename(L, lua_type(L, -1))); /* removes 'value'; keeps 'key' for next iteration */ lua_pop(L, 1); } While traversing a table, do not call lua_tolstring directly on a key, unless you know that the key is actually a string. Recall that lua_tolstring may change the value at the given index; this confuses the next call to lua_next. See function next for the caveats of modifying the table during its traversal.大体意思是说在遍历table时,除非你知道key是string类型,否则不要直接对key进行lua_tolstring操作,这是因为lua_tolstring操作可能修改指定index处的值,从而使下一次调用lua_next混淆。
简言之就是:lua_tolstring可能会破坏table的原有结构,所以不要在遍历的时候对key进行lua_tolstring操作。
而lua_tostring最终调用的也是lua_tolstring,所以问题便出在这了。
要避免此错误,不传索引数组便可解决,如:
luaoc.callStaticMethod("SdkApi", "init", {platform = "platform", debug = true})