2

我正在为 iPad 开发一个小项目,我只想运行一个脚本,该脚本将在某些函数调用后停止,然后让我稍后从同一个地方恢复脚本。事实上,我一次只在队列中做一个“线程”,所以它实际上只是 iPhone OS 和 Lua 之间的多任务处理。

static int yield__ (lua_State *L) {
//NSLog(@"Do Yield");
return lua_yield(L, 0);
}

//This function adds a script to my queue
- (void) doFileThreaded:(NSString*)filename {

NSString* path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];
const char* file = [path UTF8String];

lua_State* newThread = lua_newthread(luaState);

//Load the file for execution
if ( luaL_loadfile(newThread,file) != 0 ) {
    return;
}   
//Add file to the queue
[threads addObject:[NSValue valueWithPointer:newThread]];
}

//This Function Executes the queued threads one at a time removing them when they've finished
- (void) doThreads {

lua_State* thread = NULL;

while ( threads.count > 0 ) {

    thread = (lua_State*)[[threads objectAtIndex:0] pointerValue];

    //Resume will run a thread until it yeilds execution
    switch ( lua_resume(thread, 0) ) {
        case LUA_YIELD:
            //NSLog(@"Recieved Yield");
            return;

        case 0:
            NSLog(@"Removing Thread");
            [threads removeObjectAtIndex:0];
            thread = NULL;
            break;
        default:
            NSLog(@"Error Executing Threaded Script!");
            [threads removeObjectAtIndex:0];
            break;

    }

}

}

现在对于 Lua 代码:

function wait (seconds)

  time = os.time() + seconds;
  print("Waiting " .. os.time() .. " to " .. time);
  while ( time > os.time() ) do
    yield(); --I have written my own yield function
  end

end

print("Entered Toad Behavior");

yield();

print("Point 1");

yield();

print("point 3");

wait(1);

print("point 4");

wait(2);

print("point 5");

此代码将在第二次调用等待 lua 时崩溃。使用 BAD_MEMORY_ACCESS 或 lua_resume 有时会返回运行时错误。(我不知道如何检查错误是什么,所以如果你能帮助我,我也会很感激)那里的任何人都可以告诉我我在这里做错了什么吗?

4

1 回答 1

3

好的,我不是 100% 理解它,但我相信这与我从另一个正在执行的 lua 脚本调用 doFileThreaded 的事实有关。看起来即使 lua_State 不同,我从一个已经被 Lua 调用的函数中调用了 luaL_loadfile ,这仍然以某种方式导致“尝试跨越元方法/C调用边界”

我的解决方案是将要运行的文件的名称作为字符串保存到数组中,然后在 doThread 中调用 lua_newthread。

- (void) doFileThreaded:(NSString*)filename {

NSString* path = [[NSBundle mainBundle] pathForResource:filename ofType:nil];

//Add to queue
[threads addObject:path];
}

- (void) doThreads {

//Will run through the threads in the order they've been queued.
//Cooperative Multitasking

while ( threads.count > 0 ) {

    //If there is no thread start one
    if ( threadState == NULL ) {

        threadState = lua_newthread(luaState);

        const char* file = [[threads objectAtIndex:0] UTF8String];

        if ( luaL_loadfile(threadState,file) != 0 ) {
            NSLog(@"%s\n", lua_tostring(threadState,-1));
            [threads removeObjectAtIndex:0];
            threadState = NULL;
            return;
        }

        //Return because we don't want to resume the file right away
        //return;

    }

    //Resume will run a thread until it yeilds execution
    switch ( lua_resume(threadState, 0) ) {
        case LUA_YIELD:
            return;

        case 0:
            //New Thread
            NSLog(@"Thread Returned");
            threadState = NULL;
            [threads removeObjectAtIndex:0];
            break;

        case LUA_ERRMEM:
            NSLog(@"LUA_ERRMEM");
            NSLog(@"%s\n", lua_tostring(threadState,-1));
            [threads removeObjectAtIndex:0];
            break;

        case LUA_ERRERR:
            NSLog(@"LUA_ERRERR: error while running the error handler function");
            NSLog(@"%s\n", lua_tostring(threadState,-1));
            [threads removeObjectAtIndex:0];
            break;

        case LUA_ERRRUN:
            NSLog(@"LUA_ERRRUN: a runtime error.");
            NSLog(@"%s\n", lua_tostring(threadState,-1));
            [threads removeObjectAtIndex:0];
            break;

        default:
            NSLog(@"Error Executing Threaded Script!");
            NSLog(@"%s\n", lua_tostring(threadState,-1));
            [threads removeObjectAtIndex:0];
            break;

    }

}

}

,调试起来真的很痛苦。但它有效!!!!

于 2010-06-04T07:36:22.780 回答