satoren / kaguya

C++ binding to Lua
Boost Software License 1.0
345 stars 70 forks source link

Wrapper for Lua error throwing #14

Closed Flamefire closed 8 years ago

Flamefire commented 8 years ago

As it is possible to call C++ functions from Lua and it is possible that this goes wrong, there should be a method to throw lua errors.

2 cases:

  1. Lua calls a function, but the argument is of the wrong type. I assume (correct me here) this wrapper will directly call the error handler here. So there is no way to catch this with Luas pcall
  2. The argument passed to the function is wrong (after the wrapper calls the C++ function) e.g. an index is out of bounds. For getters it might be reasonable to return nil but if e.g. this is a valid return value too or it is an execution function that you don't want to just 'do nothing' it is better to throw an error, that lua can catch and that will be passed to the error handler otherwise.

However I did not find a function for calling lua_error in the wrapper (besides of course executing state("error('Foo bar!!!')"))

Is there something for this? If not could it be added? What about the io.openFile like behaviour that it returns the file or nil and an error message? Can this be done easily with kaguya?

satoren commented 8 years ago

Did you tried setErrorHandler?

        static void stderror_out(int status, const char* message)
        {
            std::cerr << message << std::endl;
        }

this is default error handler. output to stderr only.

If you want need throw exception at luaerror. e.g.

kaguya::State state;
state.setErrorHandler([](int status, const char* message) {throw std::runtime_error(message); });
Flamefire commented 8 years ago

I'm talking about throwing an error to Lua. So it can be handled in Lua. I show you an example:

state["test"] = kaguya::function([]{ lua_pushstring(state.state(), "Lua!"); lua_error(state.state()); });
state(" if(pcall(test)) then \n print("OK"); \n else \n print("ERROR") \n end");//ERROR
state("test()");//Lua!
satoren commented 8 years ago

I think It is mistaken lua code. pcall is first argument require function. It is not function result.

state["test"] = kaguya::function([&] { lua_error(state.state()); });
state(" if(pcall(test)) then \n print('OK'); \n else \n print('ERROR') \n end");//ERROR
Flamefire commented 8 years ago

Yes thanks. I edited the code.

What I suggest in this issue is: Wrap the call to lua_error in kaguya so it is simply state.error("Lua!")

satoren commented 8 years ago

lua_error is longjmp at default compile. I hate setjmp/longjmp with C++. memory leak. strange crash. etc..

You can use throw exception.

state["test"] = kaguya::function([&] { throw std::runtime_error("Lua!"); });
state("test()");

message to error_handler

Lua!
stack traceback:
        [C]: in function 'test'
        [string "test()"]:1: in main chunk

It 's no good ?

Flamefire commented 8 years ago

Ah, so this exception is already caught by the lua error handler? Did not know that :)

satoren commented 8 years ago

Yes. catch all exception, and notify error to LuaVM. =)