首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Luabind和coroutines

Luabind和coroutines
EN

Stack Overflow用户
提问于 2011-06-16 00:57:57
回答 1查看 1.5K关注 0票数 3

我有点搞不懂如何正确地使用润滑油。有一个模板功能:

代码语言:javascript
复制
template<class Ret> 
Ret resume_function(object const& obj, ...)

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

我目前的困惑是:

如果函数返回而不是调用,

  • 会发生什么?resume_function是否返回函数的返回值?如果您不提前知道哪些(或多少)参数将传递给yield,那么如何使用该函数?例如,如果存在多个可能的生成函数,则该函数可能调用。如果向yield

传递多个值,那么

  • 是什么类型的Ret

我只是完全误解了这一切是如何运作的吗?我想象像这样的事情。在Lua方面:

代码语言:javascript
复制
local img = loadImage("foo.png")

loadImage将是一个C++函数,它请求将映像加载到不同的线程中,然后调用lua_yield,然后用img作为参数调用luabind::resume_function

我应该将"foo.png"作为参数传递给yield吗?在调用yield之前,不将任何值传递给yield?有什么正确的方法来构造这个?我显然是误会了一些事。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-16 04:05:43

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

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

如果函数返回而不是调用

,会发生什么情况?resume_function是否返回函数的返回值?

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

,如果您不提前知道将传递哪些(或多少)参数,那么如何使用这个函数呢?例如,如果存在多个可能的生成函数,则该函数可能会调用。

这取决于你;这是你的职责。您必须开发关于生产函数作为参数接收到什么以及恢复协同服务提供的函数的约定。

,如果传递多个值以产生结果,那么Ret的类型是什么?

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

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

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

如果使用Luabind,千万不要直接调用lua_yield。在Luabind中,正确的方法是向注册的函数添加一个属性,每当从函数返回时,该属性就会产生属性。语法如下:

代码语言:javascript
复制
module(L)
[
    def("do_thing_that_takes_time", &do_thing_that_takes_time, yield)
];

也就是说,产生结果的C++函数必须总是输出。这是Luabind的一个限制,就像普通Lua一样,你可以选择是否屈服。

另外,不要忘记Lua协同器与实际线程不是一回事。它们不是先发制人的;当您显式地告诉它们使用或等效的简历调用时,它们只会执行

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

您似乎要做的是让Lua调用C++中的某个函数,该函数本身生成一个线程来执行某个进程,然后让Lua代码等待该线程完成,然后收到它的答案。

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

如果你不想让Lua脚本等到它完成的时候,协同器就可以在这里发挥作用。也就是说,您经常调用Lua脚本,但是如果C++线程没有完成,那么它就应该返回。在这种情况下,您可以这样做:

代码语言:javascript
复制
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还是其他什么)来抽取协同值,不管他们想要的多大。每次检查返回值。如果nil线程尚未完成,则为C++,否则为nil

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6366050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档