zoukankan      html  css  js  c++  java
  • CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to 'next'错调试

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

  • 相关阅读:
    85个国外Ajax例子
    如何捕获方向键
    C#版对对碰[强荐]
    如何关闭移动盘的自动播放
    常用算法大全-回溯算法
    string转换成color
    常用算法大全-分而治之算法
    常用算法大全-分枝定界
    C#游戏——极品蜜蜂V1.0
    WebService传多个参数和返回多个参数的方法
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3938099.html
Copyright © 2011-2022 走看看