3

I have an application that periodically will run a Lua script. Within the script, on occasion, I have created a custom registered Lua function to check some parameters and decide if the Lua script should continue or exit. The logic ideally should not be part of the script and I can think of using a Lua script to work around this, but I'm wondering if it is possible to stop the execution of a Lua script without ending the application.

I have a custom function written in Delphi and exposed to Lua scripts using Lua 5.1. The Lua script looks something like that shown below and the script in Lua is started using luaL_loadbuffer.

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

My custom function looks something like this, below I have provided one of my attempts where I tried to use lua_error to stop the script...

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;

When my custom function is called, I'm unsure as to how to exit the Lua script without any further evaluation. I have seen posts referring to Lua and using setjmp and longjmp in C, but I'm curious how these may translate Delphi.

In the example above, when I use lua_error, the entire program crashes with Windows doing its typical, [luarun.exe has stopped working] ...

With all of this, I'm am still pretty new to integrating Lua to Delphi and hoping that I can find some cleaner options to explore.

3
  • Which Delphi Lua import units are you using? And was your Lua DLL compiled as C, or as C++? Commented Nov 28, 2012 at 17:51
  • I do pretty much the same thing and it works fine. It sounds like something is triggering an exception. Run it under the debugger to see what's happening... Commented Nov 28, 2012 at 18:18
  • @Koscielski We have corrected your question, but the next time please write Lua correctly, see stackoverflow.com/questions/13615975 Commented Nov 29, 2012 at 4:32

1 Answer 1

1

There is no clean way to entirely abort a Lua script. The lua_error function is the correct way to signal an error. It is the caller's responsibility to catch the error and propagate it to the next caller.

If you cannot rely on the caller to cooperate, then you can try to exert more control by installing debug hooks. Then the host program will be consulted before continuing to run the script. However, the script can still avoid exiting by using pcall to catch any errors.

The crash in your program is probably not simply from setting an error. Rather, it's likely from using the wrong calling convention on your ExitIfFound function. It needs to be cdecl, but Delphi's default, if you don't specify anything else, is register. Using the wrong calling convention will give you unpredictable parameter values and can lead to a corrupted stack. If you type-casted the function or used the @ operator when you called lua_register, then you might have hidden the calling-convention mismatch from the compiler's type checker, which would have otherwise alerted you to the problem at compile time.

When compiled as C++, lua_error will use a exception instead of longjmp, but either way, the caller always catches the error. Exceptions are important, though, when your Delphi code uses compiler-managed types like string, or exception-sensitive constructs like try-finally blocks. In C mode, lua_error calls longjmp to jump directly to the waypoint set by a previous call to setjmp. That jump will skip over any exception handlers like the ones the Delphi compiler sets up to ensure the finally block runs and the string gets cleaned up.

A further headache is that since the compiler cleans up the string while exiting the function, the pointer you put on the Lua stack might not be valid by the time it's used; that depends on whether lua_pushstring makes a copy of its argument.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.