gpt4 book ai didi

Luabind 和协程

转载 作者:行者123 更新时间:2023-12-04 16:06:26 26 4
gpt4 key购买 nike

我在理解如何通过 luabind 正确使用协程时遇到一些问题。有一个模板函数:

template<class Ret> 
Ret resume_function(object const& obj, ...)

其中 (Ret) 应该包含由 Lua 传递给 yield 的值。

我目前的困惑点是:

  • 如果函数返回而不是调用 yield 会发生什么? resume_function 是否返回函数的返回值?
  • 如果您事先不知道哪些(或多少)参数将传递给 yield,您应该如何使用此函数?例如,如果有多个可能的 yield 函数,该函数可能会调用。
  • 如果将多个值传递给 yieldRet 的类型是什么?

我是不是完全弄错了这一切是如何运作的?我设想这样的事情。在 Lua 方面:

local img = loadImage("foo.png")

loadImage 将是一个 C++ 函数,它请求在不同的线程中加载图像,然后调用 lua_yield,并在一段时间后调用 luabind::resume_function img 作为参数调用。

我应该将 "foo.png" 作为参数传递给 yield 吗?在我调用 yield 之前转到另一个函数,然后从不将任何值传递给 yield?构建这个的正确方法是什么?我显然误解了这里的内容。

最佳答案

Where (Ret) is supposed to contain the values passed to yield by Lua.

Luabind 只支持单个返回值,因此它只会返回传递给 coroutine.yield 的第一个值。

What happens if the function returns rather than calling yield? Does resume_function return the function's return value?

是的,你得到它的返回值。

How are you supposed to use this function if you don't know ahead of time which (or how many) parameters will be passed to yield? For example, if there are multiple possible yielding functions the function may call.

这取决于你;他们是你的职能。您必须就屈服函数接收的参数以及恢复协程的函数提供的内容制定约定。

What is the type of Ret if multiple values are passed to yield?

随心所欲。这是模板参数。函数的参数数量与函数提供的返回值无关。

记住:Lua 函数接受任意数量的参数并且可以返回任何东西。 Luabind 所能做的就是传递您给它的参数,并将 Lua 函数的返回值转换为您期望的返回值。 Luabind 当然会对返回值进行类型检查。但您有责任确保产生/返回的函数将返回可转换为用户为 Ret 提供的类型的内容。

loadImage would be a C++ function which requests the image to be loaded in a different thread and then calls lua_yield, and some time later luabind::resume_function gets called with img as a parameter.

如果您正在使用 Luabind,切勿直接调用 lua_yield。在 Luabind 中产生的正确方法是向您注册的函数添加一个属性,该属性将在您从函数返回时产生。语法如下:

module(L)
[
def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];

也就是说,产生的 C++ 函数必须总是产生。这是 Luabind 的局限性,与常规 Lua 一样,您可以根据需要选择是否屈服。

此外,不要忘记 Lua 协程与实际线程不同。他们不是先发制人的;当您使用 coroutine.resume 或等效的 resume 调用明确告诉它们时,它们将执行。

此外,您应该永远不要从多个 C/C++ 线程运行同一个 Lua 实例; Lua 在同一个实例中不是线程安全的(这或多或少意味着同一个 lua_State 对象)。

您似乎想要做的是让 Lua 调用 C++ 中的某个函数,该函数本身会生成一个线程来执行某些过程,然后让 Lua 代码等待该线程完成,然后接收其响应。

为此,您需要为 Lua 脚本提供一个代表 C++ 线程的对象。所以你的 loadImage 函数不应该使用协程逻辑;它应该返回一个代表 C++ 线程的对象。 Lua 脚本可以询问对象是否已完成,如果已完成,则可以从中查询数据。

如果您不希望 Lua 脚本等到它完成,协程可以在这里发挥作用。也就是说,您经常调用 Lua 脚本,但如果 C++ 线程未完成,则它应该返回。在这种情况下,您可以这样做:

function loadImageAsCoroutine(imageFilename)
local cppThread = cpp.loadImage(imageFilename);

local function threadFunc(cppThread)
if(cppThread:isFinished()) then
local data = cppThread:GetImage();
return data;
else
coroutine.yield();
end
end

local thread = coroutine.create(threadFunc);

local errors, data = assert(coroutine.resume(thread, cppThread));

if(coroutine.status(thread) == "dead") then
return data;
else
return thread;
end
end

此函数返回协程图像数据本身。这个函数的调用者应该检查类型;如果类型是“thread”,那么C++线程还没有结束。否则为图像数据。

此函数的调用者可以使用一些等效的 coroutine.resume(无论是 luabind::resume_function 还是其他)来尽可能多地抽取协程。每次检查返回值。如果 C++ 线程尚未完成,它将是 nil,否则不是 nil

关于Luabind 和协程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6366050/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com