【问题标题】:Equivalent of Lua coroutine.create in C++ using lua_newthread使用 lua_newthread 在 C++ 中相当于 Lua coroutine.create
【发布时间】:2012-07-07 22:39:15
【问题描述】:

我有一个回调系统,它可以将 lua 函数添​​加到 C++ 处理程序,例如在lua中我可以做到

myCObject:AddCallback(luaFunc)

对于协程我也有同样的方法

myCObject:AddCallback(coroutine.create(luaFunc))

然后我可以使用

lua_State * pThread = lua_tothread(L, -1);
lua_resume(pThread, 0,0);

在 C++ 中

启动/恢复 lua 函数。

现在,我不想要求脚本编写者编写 coroutine.create(luaFunc) - 我只想将 lua func 自动“转换”为协程。当调用 AddCallback 时,我在堆栈上有 luaFunc - 然后我该如何继续? (使用 coroutine.create 我已经在堆栈上有一个线程)

编辑:我正在寻找使用 C API 的解决方案,例如lua_newthread

【问题讨论】:

    标签: c++ lua


    【解决方案1】:

    这个想法相当简单。首先,创建一个新线程。

    lua_State *pThread = lua_newthread(L);
    

    此函数还将该线程推送到L。下一步是将你的线程函数放到pThread 上。鉴于此时堆栈上有一个 Lua 函数,下一步就是将该函数转移到 pThread 堆栈。

    有一个专门用于在线程之间传输值的函数:lua_xmove。但是,它只传输堆栈的顶部元素。所以你需要将 Lua 函数从它在L 的堆栈中的位置复制到L 的堆栈的顶部。然后lua_xmove 到新堆栈。

    lua_pushvalue(L, #); //Where # is the index in the stack where the function is.
                         //Remember that lua_newthread pushed a value on the stack, so compensate for that.
    lua_xmove(L, pThread, 1); //Moves the function to the top of the new stack.
    

    请记住 lua_xmove 移动值,这会将其从 L 中删除。所以lua_pushvalue 推送值,lua_xmove 弹出它。所以栈顶又是pThread代表的lua_State

    之后,将您需要发送的所有参数推送到函数(显然为零),然后恢复它。

    lua_resume(pThread, 0, 0);
    

    总码:

    lua_State *pThread = lua_newthread(L);
    lua_pushvalue(L, #); //Where # is the index in the stack where the function is.
                         //Remember that lua_newthread pushed a value on the stack, so compensate for that.
    lua_xmove(L, pThread, 1); //Moves the function to the top of the new stack.
    lua_resume(pThread, 0, 0);
    

    Lua 线程(无论是在 Lua 中创建还是在 C API 中创建的)是一个 Lua 值,就像一个表、用户数据、字符串等。因此,它受到垃圾回收的影响。当 Lua 检测到没有更多对该值的引用时,它将被收集。

    记住:lua_newthread 将线程推入原始堆栈。您可以将其复制到注册表、全局环境或您打算永久驻留该线程的任何位置。仅仅保留一个指向它生成的lua_State 的指针不会确保线程保持活动状态。

    【讨论】:

    • 谢谢 - 这行得通 - 你知道 coroutine.create 是否与 lua_newthread 几乎相同吗?该线程的生命周期如何——我收集它位于用于创建线程的原始 lua_state 的某个位置——当 pThreads 堆栈顶部的函数完成时,它是否会自动进行垃圾收集?
    • 应该调用lua_resumelua_resume(pThread, nullptr, 0)吗?
    【解决方案2】:

    好久没做lua的东西了,有点生疏了。但是,我认为你想要做的是:

    • 提取luaFunc
    • 然后将coroutine.create 函数推上
    • 然后将luaFunc 推回
    • 并使用lua_pcall 将您的线程放入堆栈。

    在您的 cmets 中,您想使用 lua_newthread。我没有任何经验,但我确实找到了this answer,其中包含一个正在使用它的示例程序。

    【讨论】:

    • 这可能可行,但那将是一个非常丑陋的解决方案,我想利用现有的 lua API,例如lua_newthread
    • @Steve:是的,就像我说的,我已经有一段时间了。我运行并行 lua 脚本的方法是在我自己的轻量级线程中启动它们(比如 Windows 上的 Fibers,或 state threads library。但是,我没有看到任何人帮助你,所以我想我会折腾我的$.02.
    • @Steve:如果您想要基于lua_newthread 的解决方案,您应该在您的问题中询问。因此,请编辑您的问题以提出要求。
    • @Steve:我用指向关于lua_newthread 的 SO 问题的指针更新了我的答案。
    • @User315052 - 我以前也读过那个 - 谢谢 - 但它实际上是针对整个脚本环境(一个文件)而不是单个函数 - 我不知道如何从那里开始
    猜你喜欢
    • 1970-01-01
    • 2010-12-23
    • 2014-03-06
    • 2016-06-23
    • 2021-12-31
    • 1970-01-01
    • 2021-07-29
    • 2020-07-13
    • 1970-01-01
    相关资源
    最近更新 更多