Lua例程 [英] Lua co-routines

查看:125
本文介绍了Lua例程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to get an understanding of how I can use co-routines to "pause" a script and wait until some processing is done before resuming.

也许我在用错误的方式查看协同例程.但是我的尝试的结构类似于此

Perhaps I'm looking at co-routines in the wrong way. But my attempt is structured similar to the example given in this answer.

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

The loop in loop.lua never reaches a second iteration, and hence never reaches the i == 4 condition required to exit the running loop in the C code. If I do not yield in loop.lua, then this code performs as expected.

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;
}

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()

添加了赏金,希望能对如何实现这一目标有所帮助.

Added a bounty, to hopefully get some help on how to accomplish this.

推荐答案

lua_resume返回的代码2是LUA_ERRRUN.检查Lua堆栈顶部的字符串以查找错误消息.

Return code 2 from lua_resume is a LUA_ERRRUN. Check the string on the top of the Lua stack to find the error message.

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

A similar pattern has worked for me, though I did use coroutine.yield instead of lua_yield and I'm in C rather than C++. I don't see why your solution wouldn't work

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

On your resume call, it's not clear if you're over simplifying for an example, but I'd make the following changes in your while loop:

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);
  }
}

要进行调试,请在运行简历之前添加以下内容.您有一个字符串被压入堆栈中的某个位置:

For debugging, add the following before you run your resume. You've got a string getting pushed on the stack somewhere:

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);

哦,真可惜,我不敢相信我还没有看到这一点,因为您不能直接产生pcall,所以您不想运行luaL_dofile,因为据我所知,这是在dofile中发生的事情(5.2将通过它,但我认为您仍然需要lua_resume).切换到此:

Oh good grief, I can't believe I didn't see this already, you don't want to run luaL_dofile when you're going to yield because you can't yield a pcall directly as best I know, which is what happens in the dofile (5.2 will pass it through, but I think you still need the lua_resume). Switch to this:

luaL_loadfile(cL, "scripts/loop.lua");

这篇关于Lua例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆