Where (Ret) 应该包含 Lua 传递给 yield 的值。
Luabind 只支持单个返回值,所以它只会返回传递给coroutine.yield 的第一个值。
如果函数返回而不是调用yield会发生什么? resume_function 是否返回函数的返回值?
是的,你得到了它的返回值。
如果您不提前知道哪些(或多少)参数将被传递给 yield,您应该如何使用此函数?例如,如果有多个可能的屈服函数,该函数可能会调用。
这取决于你;它们是你的功能。您必须制定关于产生函数接收什么作为参数以及恢复协程的函数提供什么的约定。
如果多个值传递给yield,Ret的类型是什么?
随心所欲。这是模板参数。函数的参数数量与函数提供的返回值无关。
记住:Lua 函数可以接受任意数量的参数并且可以返回任何值。 Luabind 所能做的就是传递你给它的参数,并将 Lua 函数的返回值转换为你期望的返回值。 Luabind 当然会对返回值进行类型检查。但您有责任确保产生/返回的函数将返回可转换为用户为 Ret 提供的类型的内容。
loadImage 将是一个 C++ 函数,它请求将图像加载到不同的线程中,然后调用 lua_yield,一段时间后 luabind::resume_function 以 img 作为参数调用。
如果您使用的是 Luabind,请不要直接致电 lua_yield。在 Luabind 中 yield 的正确方法是向您注册的函数添加一个属性,该属性将在您从函数返回时产生。语法如下:
module(L)
[
def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];
也就是说,产生的 C++ 函数必须总是产生。这是 Luabind 的一个限制,与常规 Lua 一样,您可以根据需要选择是否屈服。
另外,不要忘记 Lua 协程与实际线程不同。他们不是先发制人的;他们将仅在您使用 coroutine.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
这个函数返回一个协程或图像数据本身。这个函数的调用者应该检查类型;如果类型是“线程”,那么 C++ 线程还没有完成。否则为图片数据。
这个函数的调用者可以用coroutine.resume 的等效值(无论是 luabind::resume_function 还是其他)来抽取他们想要的协程。每次检查返回值。如果 C++ 线程尚未完成,则为 nil,否则为 nil。