Lua 卢阿宾德和科罗因斯

Lua 卢阿宾德和科罗因斯,lua,coroutine,luabind,Lua,Coroutine,Luabind,我在理解如何正确使用与luabind的协同程序时遇到了一些困难。有一个模板函数: template<class Ret> Ret resume_function(object const& obj, ...) LoDimige将是一个C++函数,它要求图像加载在不同的线程中,然后调用 LuaYouDeule,稍后的某个时候 LuabnD::ReuMeMyFuffy以 IMG作为参数调用。 我是否应该将“foo.png”作为参数传递给yield?在调用yield之前,先

我在理解如何正确使用与luabind的协同程序时遇到了一些困难。有一个模板函数:

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

<代码> LoDimige<代码>将是一个C++函数,它要求图像加载在不同的线程中,然后调用<代码> LuaYouDeule,稍后的某个时候<代码> LuabnD::ReuMeMyFuffy<代码>以<代码> IMG作为参数调用。 我是否应该将

“foo.png”
作为参数传递给
yield
?在调用
yield
之前,先将任何值传递给另一个函数,然后再调用
yield
?正确的结构方式是什么?我显然误解了一些事情

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

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

如果函数返回而不是调用yield,会发生什么?resume_函数是否返回函数的返回值

是的,您可以得到它的返回值

如果您事先不知道哪些(或多少)参数将被传递给yield,您应该如何使用此函数?例如,如果存在多个可能的屈服函数,则该函数可以调用

这取决于你;它们是你的功能。您必须制定关于屈服函数作为参数接收的内容以及恢复协同路由的函数提供的内容的约定

如果将多个值传递给yield,Ret的类型是什么

不管你想要什么。这是模板参数。函数的参数数量与函数提供的返回值无关

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

LogiaGe是一个C++函数,它要求图像加载在不同的线程中,然后调用LuaYAG屈服,并且稍后的Lababd::ReuMeMyFuffic被调用以IMG作为参数。 如果您正在使用Luabind,请不要直接调用

lua\u 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_状态对象)

你想做的是让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\u函数还是其他函数)来泵送协同路由,不管他们想要多少。每次检查返回值。如果C++线程没有完成,而不是代码> NIL< /COD>,则将是<代码> nIL/COD>。否则,

谢谢。你回答的前半部分很有帮助。但我认为,下半年并不是解决这个问题的最佳方式(投票很少是这样)。有了您的输入,我想我脑子里已经有了一幅图,关于如何编写一个合适的协程调度器,以允许这种阻塞调用按我所希望的方式工作。事实上,我已经做到了。这很复杂,但我现在可以从Lua进行这样的阻塞调用,而不需要额外的复杂性或轮询。谢谢你的帮助!
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