Lua合作例程

dec*_*iar 7 c++ scripting lua coroutine

我试图了解如何使用协同例程来"暂停"一个脚本并等待一些处理完成后再恢复.

也许我正在以错误的方式看待惯例.但我的尝试结构类似于这个答案中给出的例子.

循环loop.lua永远不会达到第二次迭代,因此永远不会达到i == 4退出C代码中的运行循环所需的条件.如果我不屈服loop.lua,则此代码按预期执行.

main.cpp中

#include <lua/lua.hpp>

bool running = true;

int lua_finish(lua_State *) {
    running = false;
    printf("lua_finish called\n");
    return 0;
}
int lua_sleep(lua_State *L) {
    printf("lua_sleep called\n");
    return lua_yield(L,0);
}

int main() {
    lua_State* L = lua_open();
    luaL_openlibs(L);

    lua_register(L, "sleep", lua_sleep);
    lua_register(L, "finish", lua_finish);

    luaL_dofile(L, "scripts/init.lua");

    lua_State* cL = lua_newthread(L);
    luaL_dofile(cL, "scripts/loop.lua");

    while (running) {
        int status;
        status = lua_resume(cL,0);
        if (status == LUA_YIELD) {
            printf("loop yielding\n");
        } else {
            running=false; // you can't try to resume if it didn't yield
            // catch any errors below
            if (status == LUA_ERRRUN && lua_isstring(cL, -1)) {
                printf("isstring: %s\n", lua_tostring(cL, -1));
                lua_pop(cL, -1);
            }
        }
    }

    luaL_dofile(L, "scripts/end.lua");
    lua_close(L);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

loop.lua

print("loop.lua")

local i = 0
while true do
    print("lua_loop iteration")
    sleep()

    i = i + 1
    if i == 4 then
        break
    end
end

finish()
Run Code Online (Sandbox Code Playgroud)

编辑:添加了赏金,希望能得到一些如何实现这一目标的帮助.

BMi*_*tch 4

返回代码 2 来自lua_resumeis a LUA_ERRRUN。检查Lua堆栈顶部的字符串以查找错误消息。

类似的模式对我有用,尽管我确实使用了coroutine.yield而不是lua_yield并且我使用的是 C 而不是 C++。我不明白为什么你的解决方案不起作用

在您的简历通话中,不清楚您是否过度简化了示例,但我会在 while 循环中进行以下更改:

int status;
status=lua_resume(cL,0);
if (status == LUA_YIELD) {
  printf("loop yielding\n");
}
else {
  running=false; // you can't try to resume if it didn't yield
  // catch any errors below
  if (status == LUA_ERRRUN && lua_isstring(cL, -1)) {
    printf("isstring: %s\n", lua_tostring(cL, -1));
    lua_pop(cL, -1);
  }
}
Run Code Online (Sandbox Code Playgroud)

编辑2:

为了进行调试,请在运行简历之前添加以下内容。你有一个字符串被压入堆栈的某个地方:

int status;
// add this debugging code
if (lua_isstring(cL, -1)) {
  printf("string on stack: %s\n", lua_tostring(cL, -1));
  exit(1);
}
status = lua_resume(cL,0);
Run Code Online (Sandbox Code Playgroud)

编辑3:

luaL_dofile噢,天哪,我不敢相信我还没有看到这一点,当你要屈服时你不想运行,因为据我所知,你无法直接产生 pcall,这就是发生的情况dofile(5.2将通过它,但我认为你仍然需要lua_resume)。切换到这个:

luaL_loadfile(cL, "scripts/loop.lua");
Run Code Online (Sandbox Code Playgroud)