在C++中使用lua_newthread实现与Lua中coroutine.create等价的功能。

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

myCObject:AddCallback(luaFunc)

对于协程,我也有相同的操作:

myCObject:AddCallback(coroutine.create(luaFunc))

然后,我可以在 C++ 中使用以下命令:

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

来启动/恢复 lua 函数。

现在,我不想让脚本编写者编写 coroutine.create(luaFunc),而是希望自动“将” lua 函数转换为协程。当调用 AddCallback 时,我在堆栈上有 luaFunc,然后我该怎么做?(使用 coroutine.create,我已经有一个线程在堆栈上)

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

点赞
用户315052
用户315052

我很久没有进行 lua 方面的工作了,所以有点生疏。但是,我认为你想要做的是:

  • 提取 luaFunc
  • 推入 coroutine.create 函数
  • 再将 luaFunc 推回
  • 使用 lua_pcall 将你的线程推到栈上。

从你的评论中可以看出,你想要使用 lua_newthread。我没有任何经验,但我在 此回答 中找到了一个使用它的示例程序。

2012-07-08 00:17:29
用户734069
用户734069

这个想法非常简单。首先,你创建一个新线程。

lua_State *pThread = lua_newthread(L);

这个函数也将该线程推到 L 上。下一步是将你的线程函数传递给 pThread。在这一点上,给定你在堆栈上有一个 Lua 函数,你的下一步是将该函数从 L 的堆栈传递到 pThread 的堆栈。

有一个专门用于在线程之间传递值的函数:lua_xmove。然而,它只传递堆栈顶部的元素。因此,你需要将 Lua 函数从它在 L 的堆栈上的位置复制到 L 的堆栈顶部。然后,将 lua_xmove 移动到新堆栈。

lua_pushvalue(L, #); //其中 # 是函数在堆栈中的索引。
                     //记得 lua_newthread 推了一个值到堆栈上,所以要进行补偿。
lua_xmove(L, pThread, 1); //将函数移动到新堆栈的顶部。

记住,lua_xmove 移动 值,这将它从 L 中移除。所以,lua_pushvalue 推送了该值,而 lua_xmove 弹出了它。因此,堆栈的顶部再次是由 pThread 表示的 lua_State

之后,将你需要发送给函数的所有参数推送(显然是零),并恢复该函数。

lua_resume(pThread, 0, 0);

完整代码:

lua_State *pThread = lua_newthread(L);
lua_pushvalue(L, #); //其中 # 是函数在堆栈中的索引。
                     //记得 lua_newthread 推了一个值到堆栈上,所以要进行补偿。
lua_xmove(L, pThread, 1); //将函数移动到新堆栈的顶部。
lua_resume(pThread, 0, 0);

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

记住:lua_newthread 将线程推到原始堆栈上。你可以将其复制到注册表、全局环境或任何你想让该线程永久驻留的位置。仅仅保持对它生成的 lua_State 的指针 不能 确保该线程保持活动状态。

2012-07-08 17:48:13