Mac OS X 10.5兼容性,需要Lua 5.0兼容性(因此无法使用当前批次的LuaObjc桥接。)
我的lua脚本生成一个包含数万个字符串的索引表。
基本问题:如何使用换行符分隔符将这些字符串连接到一个字符串,快速?
美中不足:即使使用垃圾收集友好的concat代码(在stackoverflow提供),结果也需要很长时间才能达到此目的。 (对于蛮力解决方案,10秒对1分钟。)
建议的解决方案:使用NSArray的-componentsJoinedByString方法将作业卸载到Cocoa,可以在几分之一秒内完成。
美中不足:如何从Lua获取表数据到Cocoa?
该脚本调用已注册的C函数,并将其传递给表。 C函数试图抓取堆栈上的表:
// Get an NSArray of strings from the first argument on the stack (a table).
NSArray *strings = nsArrayFromIndexedTable(luaState, index_1Based);
...
// Given a simple table consisting of numbers or strings, returns an NSArray.
// Nested subtables are not followed.
NSArray * nsArrayFromIndexedTable(lua_State *L, int argIdx)
{
// (Allegedly) stops GC.
lua_setgcthreshold(L, INT_MAX);
// Arg must be a table.
luaL_checktype(L, argIdx, LUA_TTABLE);
// Get num elements in table, build an array with that many.
int count = luaL_getn(L, 1);
NSMutableArray *array = [NSMutableArray arrayWithCapacity: count];
int i;
for (i = 1; i <= count; i++) {
lua_rawgeti(L, argIdx, i);
int valueType = lua_type(L, -1);
id value = 0x00;
if (valueType is_eq LUA_TNUMBER) {
value = [NSNumber numberWithDouble:lua_tonumber(L, -1)];
} else if (valueType is_eq LUA_TSTRING) {
value = [NSString stringWithUTF8String:lua_tostring(L, -1)];
}
if (value) {
[array addObject:value];
}
}
// Resume GC
lua_setgcthreshold(L, 0); // INTERMITTENT EXC_BAD_ACCESS CRASH HERE!!!!
return array;
}
问题:使用(非常大的)Lua字符串表(间歇性地)调用此函数会导致EXC_BAD_ACCESS。
调试器结果是零星的;有时候没有提供任何有用的东西,但我已经能够收集到:
如果包含这些Lua GC行,则崩溃发生在函数结尾附近的lua_setgcthreshold。
但是......如果这些Lua GC行被注释掉,则崩溃发生在[array addObject:value]
(NSZombieEnabled已启用,但未提供有用信息。)
感谢任何帮助。
答案 0 :(得分:0)
这:
int count = luaL_getn(L, 1);
应该是:
int count = luaL_getn(L, argIdx);
因此,您可能会得到错误的行数并扫描表的末尾。
答案 1 :(得分:0)
也许你的C堆太多了。我不熟悉Cocoa,但我想Lua值不需要一直可访问 - 字符串应该被复制到NSString中。如果是这样,请尝试在循环结束时包含lua_pop(L, 1)
,以清理C堆栈并防止其增长。