我可以在Delphi中使用自定义函数停止Lua脚本而不退出应用程序吗?

时间:2012-11-28 16:26:15

标签: delphi lua

我有一个定期运行Lua脚本的应用程序。在脚本中,有时,我创建了一个自定义注册的Lua函数来检查一些参数,并决定是否应该继续或退出Lua脚本。理想情况下,逻辑不应该是脚本的一部分,我可以考虑使用Lua脚本来解决这个问题,但我想知道是否可以在不结束应用程序的情况下停止执行Lua脚本。

我有一个用Delphi编写的自定义函数,并使用Lua 5.1暴露给Lua脚本。 Lua脚本看起来如下所示,Lua中的脚本使用luaL_loadbuffer启动。

io.write("Script starting\n");
--Custom Function
ExitIfFound();
io.write("Script continuing\n");

我的自定义函数看起来像这样,下面我提供了一个尝试使用lua_error停止脚本的尝试...

function ExitIfFound(LuaState: TLuaState): Integer;
var
  s: AnsiString;
begin
  s := 'ExitIfFound ending script, next Lua script line not called';
  lua_pushstring(LuaState, PAnsiString(s));
  lua_error(LuaState);
end;

当调用我的自定义函数时,我不确定如何在没有任何进一步评估的情况下退出Lua脚本。我看过帖子引用Lua并在C中使用setjmplongjmp,但我很好奇这些文章如何翻译Delphi。

在上面的示例中,当我使用lua_error时,整个程序崩溃,Windows执行其典型的[luarun.exe has stopped working] ...

有了这一切,我仍然很难将Lua集成到Delphi,并希望我能找到一些更清晰的选择来探索。

1 个答案:

答案 0 :(得分:1)

没有干净的方法可以完全中止Lua脚本。 lua_error函数是发出错误信号的正确方法。调用者有责任捕获错误并将其传播给下一个调用者。

如果您不能依赖调用者进行合作,那么您可以尝试以通过installing debug hooks施加更多控制。然后,在继续运行脚本之前,将咨询主程序。但是,the script can still avoid exiting by using pcall to catch any errors

程序中的崩溃可能不仅仅是设置错误。相反,它可能来自您ExitIfFound函数的错误调用约定。它需要是cdecl,但是Delphi的默认值,如果你没有指定其他东西,就是寄存器。使用错误的调用约定将为您提供不可预测的参数值,并可能导致堆栈损坏。如果您在调用@时键入了该函数或使用了lua_register运算符,那么您可能已经隐藏了编译器类型检查器中的调用约定不匹配,否则会提醒您注意该问题在编译时。

当编译为C ++时,lua_error将使用异常而不是longjmp,但无论如何,调用者总是捕获错误。但是,当您的Delphi代码使用编译器管理的类型(如string)或异常敏感的构造(如try - finally块时,例外很重要。在C模式下,lua_error调用longjmp直接跳转到之前调用setjmp所设置的航点。该跳转将跳过任何异常处理程序,例如Delphi编译器设置的异常处理程序,以确保finally块运行并清除字符串。

进一步令人头疼的是,由于编译器在退出函数时清除了字符串,因此放在Lua堆栈上的指针在使用时可能无效;这取决于lua_pushstring是否复制了其参数。