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})
CCLuaObjcBridge调Objective-C方法传索引数组报invalid key to 'next'错调试的更多相关文章
- 关于PHP索引数组unset某key后json_encode相关问题踩坑记录
<?php $a = [1,2,3]; var_dump(json_encode($a)); #string(7) "[1,2,3]" unset($a[0]); var_d ...
- wcf上传字节数组报错问题
为了实现上传大文件所以我们要如下设置最大值,其中security是设置访问服务的认证,此处是把它设置成为不认证,transferMode就是设置运用流的模式 <webHttpBinding> ...
- LeetCode竞赛题:K 次取反后最大化的数组和(给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。)
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次.(我们可以多次选择同一个索引 i.) 以这种方式修改数组后 ...
- js原生方法传参的细节(面试必问)
废话不说,直接上题. slice(),接收两个参数,第一个为开始index(从0开始),第二个为结束的index(也是从0开始,但是不包括index本身,只到index-1).返回值是截取的数组,原数 ...
- java基础:方法的定义和调用详细介绍,方法同时获取数组最大值和最小值,比较两个数组,数组交换最大最小值,附练习案列
1. 方法概述 1.1 方法的概念 方法(method)是将具有独立功能的代码块组织成为一个整体,使其具有特殊功能的代码集 注意: 方法必须先创建才可以使用,该过程成为方法定义 方法创建后并不是直接可 ...
- JS 索引数组、关联数组和静态数组、动态数组
JS 索引数组.关联数组和静态数组.动态数组 数组分类: 1.从数组的下标分为索引数组.关联数组 var ary1 = [1,3,5,8]; //按索引去取数组元素,从0开始(当然某些语言实现从1开始 ...
- mongodb-$type、limit、skip、sort方法、索引、聚合
一.$type操作符 $type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果. MongoDB 中可以使用的类型如下表所示: 类型 数字 备注 Double 1 String 2 ...
- C#高级功能(四)扩展方法和索引
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用.扩展方法被定义为静态方法,但 ...
- wrong number of arguments,java方法反射时数组参数的坑
java方法中只有一个参数是数组,反射的时候我们不能想当然的传歌数组进去,传数组进去的时候表示多个参数. 两个数组不是一个意思啊. 我们应该把数组转为objet,这样才表示一个参数. import j ...
随机推荐
- C# webBrowser操作 javascript
using System; using System.Windows.Forms; namespace Demo { public partial class Form1 : Form { publi ...
- 设置静态IP
设定IP $sudo vi/etc/network/interfaces autolo iface lo inet loopback 加入下面内容 autoeth0 iface eth0inet st ...
- Linux Crontab 定时任务使用总结
任务调度的crond常用命令 crond 是linux用来定期执行程序的命令.当安装完成操作系统之后,默认便会启动此任务调度命令.crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便 ...
- C++(MFC)中WebBrowser去除3D边框的方法(实现IDocHostUIHandler接口)
先说实在的:最终解决办法是实现IDocHostUIHandler接口,在GetHostInfo方法里解决,但“实现接口”意味着QueryInterface.AddRef.Release三个方法必须实现 ...
- oracle实现远程连接超简单;枚举与剪枝();PowerDesigner生成数据库代码注意里面的双引號,应该去掉
点击開始,查看netManager,点击面板的监听程序,默认仅仅有地址1且标记着localhost.新建一个地址,输入本机IP,又一次开启监听程序就可以 △△△ * △△ = △△△△ 某3位数乘以2 ...
- 利用SQL语句实现分页
1.概述 在网页中如果显示的数据太多就会占据过多的页面,而且显示速度也会很慢.为了控制每次在页面上显示数据的数量,就可以利用分页来显示数据. 2.技术要点 在SQL Server中要实现SQL分页,需 ...
- Delphi TStream 详细介绍
Delphi TStream 详细介绍Stream对象,又称流式对象,是TStream.THandleStream.TFileStream.TMemoryStream.TResourceStream和 ...
- 推动Common Lisp的实际应用
推动Common Lisp的实际应用 推动Common Lisp的实际应用
- extjs表单
Ext.onReady(function(){ Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif'; Ext.QuickTi ...
- dwExStyle和dwStyle的说明(Delphi SDK窗口)
dwExStyle: :指定窗口的扩展风格.该参数可以是下列值: WS_EX_ACCEPTFILES:指定以该风格创建的窗口接受一个拖拽文件. WS_EX_APPWINDOW:当窗口可见时,将一个顶层 ...