ThePhD / sol2

Sol3 (sol2 v3.0) - a C++ <-> Lua API wrapper with advanced features and top notch performance - is here, and it's great! Documentation:
http://sol2.rtfd.io/
MIT License
4.06k stars 493 forks source link

Am I just doing something wrong? #1489

Open ethindp opened 1 year ago

ethindp commented 1 year ago

I've read the docs and am trying to build a REPL, of sorts, in a QT application. The application is a TCP-based game (kinda like a MUD of old) and I'm running into an issue that just seems... Really weird. I'm using QT, so maybe translation is going wrong there, but I (don't) think so, since my debug output looks fine. If I try to execute a simple bit of Lua code like "3+2" or "3.33", I get a syntax error. If I try to execute a math function (I added my own math table) (say, math.sqrt(88.5)), a panic occurs. I haven't opened any libraries, so maybe that's why, but I'm executing evaluations like this:

auto BuiltinCommandInterpreter::evaluate_lua_fragment(const std::string fragment) -> std::string {
    qInfo() << "Fragment" << fragment.data() << "is about to be evaluated...";
    try {
        sol::protected_function_result pfr = lua.safe_script(fragment, &sol::script_throw_on_error);
        if (!pfr.valid()) {
            sol::error err = pfr;
            return err.what();
        } else {
            return pfr.get<std::string>();
        }
    } catch (std::exception& ex) {
        return ex.what();
    }
}

(As an aside, Sol2 is printing stuff to the console... Is there some way of preventhing that?)

Rochet2 commented 1 year ago

You cannot use libraries like math unless you open them, so thats that. You can open all libraries with lua.open_libraries(); or specific libraries by giving a list to the function (as seen here).

As for the simpler statement 3+2, is that exactly the code you run? Because lua does not accept evaluating statements like that. As you can try in the lua demo here, and see in the image here. This is because Lua requires all statements to be either assignments, function calls, control structures (such as if/else or while loops), or a combination of these.

REPLs may add a workaround where they add return before the code to be executed. You can see the workaround in action in the official lua.c here. Take a peek at the usage and definition of addreturn in it. Here is a comment from the source:

/ Read a line and try to load (compile) it first as an expression (by adding "return " in front of it) and second as a statement. Return the final status of load/call with the resulting function (if any) in the top of the stack. /

Rochet2 commented 1 year ago

(As an aside, Sol2 is printing stuff to the console... Is there some way of preventhing that?)

What exactly is being printed and in what situation?

ethindp commented 1 year ago

@Rochet2 Sol2 is printing any errors that I catch to the console as well as passing them to my exception handler. For example, if I cause a runtime error (via error(...)) (I got evaluation working, thank you :D), I see, on my end:

sol: runtime error: [string "return error("Hi")"]:1: Hi
stack traceback:
        [C]: in function 'base.error'
        [string "return error("Hi")"]:1: in main chunk

As well as this on the console (SSH):

[sol2] An error occurred and has been passed to an error handler: sol: runtime error: [string "return error("Hi")"]:1: Hi
stack traceback:
        [C]: in function 'base.error'
        [string "return error("Hi")"]:1: in main chunk

And I'm wondering how to prevent that (do I need to pass in a custom lambda for the error handler?).

Rochet2 commented 1 year ago

Hmm, do you happen to have SOL_PRINT_ERRORS set on? Looks like it might print, as seen here https://github.com/ThePhD/sol2/blob/eab1430ccdbf61a0d61d11bf86b4975838dcfb9a/include/sol/state_handling.hpp#LL152C15-L152C31

ethindp commented 1 year ago

@Rochet2 .... No? I never defined it, just enabled all safeties so maybe that enabled it?

devgs commented 1 year ago

Even though the doc says that SOL_PRINT_ERRORS 'Not turned on by default', in reality, it is enabled by SOL_ALL_SAFETIES_ON.

Given that most people define SOL_ALL_SAFETIES_ON it would be also wise to define them both:

#define SOL_PRINT_ERRORS 0
#define SOL_ALL_SAFETIES_ON 1

As it's a rarely a good idea to output something to stdout/stderr in a real application.

Rochet2 commented 1 year ago

Even though the doc says that SOL_PRINT_ERRORS 'Not turned on by default', in reality, it is enabled by SOL_ALL_SAFETIES_ON.

Sounds like unintended bug then. I cant see why documentation would say different than actual behaviour. Seems docs are from 5 years ago here, but the code was changed 3 years ago as a part of a mass change here.

Make a PR to disable it by default if not set?