我正在使用 lua coroutines (lua 5.1) 为应用程序创建插件系统。我希望使用协程,以便插件可以像一个单独的应用程序一样运行,每个处理帧产生一次。插件程序通常遵循如下公式:
function Program(P)
-- setup --
NewDrawer(function()
-- this gets rendered in a window for this plugin program --
drawstuff(howeveryouwant)
end)
-- loop --
local continue = true
while continue do
-- frame by frame stuff excluding rendering (handled by NewDrawer) --
P = coroutine.yield()
end
end
每个插件每帧在应用程序的主循环中恢复一次。然后,当绘图开始时,每个插件都有一个单独的窗口,它在其中执行传递给 NewDrawer 的函数。
像这样的东西:
while MainContinue do
-- other stuff left out --
ExecutePluginFrames() -- all plugin coroutines resumed once
BeginRendering()
-- other stuff left out --
RenderPluginWindows() -- functions passed to NewDrawer called.
EndRendering()
end
但是我发现,每当渲染中发生错误时,这突然开始表现得很奇怪,并弄乱了我原本强大的错误处理系统。我花了一点时间来理解正在发生的事情,但似乎我期望在主线程的调用堆栈中的对 WIN:Draw() 的调用(因为它由主应用程序处理)实际上是导致隐式跳转到协程的调用堆栈。
起初的问题是程序突然关闭,没有有用的错误输出。然后在查看插件程序中定义的渲染函数的堆栈回溯后,我发现从主线程到窗口的 Draw 的所有内容都不存在,并且该 yield 在调用堆栈中。
似乎因为窗口是在线程和绘图函数中创建的,它们正在由该线程的调用堆栈处理,这是一个问题,因为这意味着它们不在主线程中设置的 pcall 之外。
这假设会发生吗?它是 C 源代码中的错误/快捷方式的结果吗?我做错了什么或至少做得不够正确?有没有办法干净地处理这个?