【问题标题】:Can I have a custom function stop a Lua script in Delphi without exiting the application?我可以在不退出应用程序的情况下让自定义函数在 Delphi 中停止 Lua 脚本吗?
【发布时间】:2012-11-29 08:12:48
【问题描述】:

我有一个定期运行 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 还是很陌生,希望我能找到一些更简洁的选择来探索。

【问题讨论】:

  • 您使用的是哪些 Delphi Lua 导入单元?你的 Lua DLL 是编译为 C 还是 C++?
  • 我做的几乎一样,而且效果很好。听起来好像有什么东西触发了异常。在调试器下运行它,看看发生了什么......
  • @Koscielski 我们已经更正了你的问题,但是下次请正确写Lua,见stackoverflow.com/questions/13615975

标签: delphi lua


【解决方案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 是否复制其参数。

【讨论】:

    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2018-02-23
    • 1970-01-01
    • 2012-05-17
    • 2012-06-07
    相关资源
    最近更新 更多