CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to 'next'错调试

来源:互联网 发布:淘宝91邀请码多少钱 编辑:程序博客网 时间:2024/05/01 06:10

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})

4 0
原创粉丝点击