Lua - Cocoa - 字符串拼接 - 将简单表转换为 NSArray

Mac OS X 10.5兼容性,需要Lua 5.0兼容性(因此不能使用当前批量的LuaObjc桥)。

我的Lua脚本生成一个包含成千上万个字符串的索引表。

基本问题:如何快速将这些字符串与换行符连接为一个字符串?

瓶颈:即使使用堆栈溢出友好的连接代码(在stackoverflow上提供),结果也太慢了(brute force解决方案需要1分钟,而此方法需10秒)。

提议解决方案:将工作卸载到Cocoa中,在那里可以使用NSArray的- componentsJoinedByString方法在一秒钟内完成。

新问题:如何将表数据从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已启用,但未提供有用的信息。)

任何帮助都将不胜感激。

原文链接 https://stackoverflow.com/questions/3655420

点赞
stackoverflow用户434004
stackoverflow用户434004

这是:

int count = luaL_getn(L, 1);

应该改为:

int count = luaL_getn(L, argIdx);

这样,您就可以避免获取到错误的行数,并且在表格末尾进行扫描。

2010-09-07 03:22:14
stackoverflow用户221509
stackoverflow用户221509
Maybe you grow your C stack too much. 
我不熟悉Cocoa,但我猜Lua值不需要一直可访问——字符串应该被复制到NSString中。如果是这样,请尝试在循环结束时包含一个`lua_pop(L,1)`,以清理C堆栈,并防止其增长。
2010-09-07 06:52:29