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\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})
上一篇:NYOJ-16-矩形嵌套 记忆化搜索


下一篇:IE提示是否只查看安全传送的网页内容