【问题标题】:Lua - Cocoa - String Concat - Simple Table to NSArrayLua - Cocoa - String Concat - 到 NSArray 的简单表
【发布时间】:2011-04-08 23:57:30
【问题描述】:

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

我的 lua 脚本生成一个包含数万个字符串的索引表。

基本问题:如何快速将这些带有换行符分隔符的字符串连接到一个字符串?

美中不足:即使使用垃圾收集友好的 concat 代码(在 stackoverflow 提供),结果也需要很长时间才能达到此目的。 (10 秒对 1 分钟的蛮力解决方案。)

建议的解决方案:将作业卸载到 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 已开启,但未提供有用信息。)

感谢任何帮助。

【问题讨论】:

    标签: cocoa lua


    【解决方案1】:

    这个:

    int count = luaL_getn(L, 1);
    

    应该是:

    int count = luaL_getn(L, argIdx);    
    

    因此,您可能会得到不正确的行数并扫描表的末尾。

    【讨论】:

    • 谢谢格雷厄姆。我已经进行了更改,但可惜,问题仍然存在。它在 luaC_collectgarbage() 中死亡。干杯。
    【解决方案2】:

    也许你的 C 堆栈增长太多了。我不熟悉 Cocoa,但我猜 Lua 值不需要一直都可以访问——字符串应该被复制到 NSString 中。如果是这样,请尝试在循环末尾包含 lua_pop(L, 1),以清理 C 堆栈并防止其增长。

    【讨论】:

      猜你喜欢
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-21
      相关资源
      最近更新 更多