Error Handling

pcall errorfunc

As mentioned in the Lua documentation, it is possible to pass an error handler function to lua_pcall(). Luabind makes use of lua_pcall() internally when calling member functions and free functions. It is possible to set the error handler function that Luabind will use globally:

typedef int(*pcall_callback_fun)(lua_State*);
void set_pcall_callback(pcall_callback_fun fn);

This is primarily useful for adding more information to the error message returned by a failed protected call. For more information on how to use the pcall_callback function, see errfunc under the pcall section of the lua manual.

For more information on how to retrieve debugging information from lua, see the debug section of the lua manual.

The message returned by the pcall_callback is accessable as the top lua value on the stack. For example, if you would like to access it as a luabind object, you could do like this:

catch(error& e)
{
    object error_msg(from_stack(e.state(), -1));
    std::cout << error_msg << std::endl;
}

file and line numbers

If you want to add file name and line number to the error messages generated by luabind you can define your own pcall errorfunc. You may want to modify this callback to better suit your needs, but the basic functionality could be implemented like this:

int add_file_and_line(lua_State* L)
{
   lua_Debug d;
   lua_getstack(L, 1, &d);
   lua_getinfo(L, "Sln", &d);
   std::string err = lua_tostring(L, -1);
   lua_pop(L, 1);
   std::stringstream msg;
   msg << d.short_src << ":" << d.currentline;

   if (d.name != 0)
   {
      msg << "(" << d.namewhat << " " << d.name << ")";
   }
   msg << " " << err;
   lua_pushstring(L, msg.str().c_str());
   return 1;
}

For more information about what kind of information you can add to the error message, see the debug section of the lua manual.

Note that the callback set by set_pcall_callback() will only be used when luabind executes lua code. Anytime when you call lua_pcall yourself, you have to supply your function if you want error messages translated.

lua panic

When lua encounters a fatal error caused by a bug from the C/C++ side, it will call its internal panic function. This can happen, for example, when you call lua_gettable on a value that isn’t a table. If you do the same thing from within lua, it will of course just fail with an error message.

The default panic function will exit() the application. If you want to handle this case without terminating your application, you can define your own panic function using lua_atpanic. The best way to continue from the panic function is to make sure lua is compiled as C++ and throw an exception from the panic function. Throwing an exception instead of using setjmp and longjmp will make sure the stack is correctly unwound.

When the panic function is called, the lua state is invalid, and the only allowed operation on it is to close it.

For more information, see the lua manual section 3.19.

structured exceptions (MSVC)

Since lua is generally built as a C library, any callbacks called from lua cannot under any circumstance throw an exception. Because of that, luabind has to catch all exceptions and translate them into proper lua errors (by calling lua_error()). This means we have a catch(...) {} in there.

In Visual Studio, catch (...) will not only catch C++ exceptions, it will also catch structured exceptions, such as segmentation fault. This means that if your function, that gets called from luabind, makes an invalid memory adressing, you won’t notice it. All that will happen is that lua will return an error message saying “unknown exception”.

To remedy this, you can create your own exception translator:

void straight_to_debugger(unsigned int, _EXCEPTION_POINTERS*)
{ throw; }

#ifdef _MSC_VER
   ::_set_se_translator(straight_to_debugger);
#endif

This will make structured exceptions, like segmentation fault, to actually get caught by the debugger.

Error messages

These are the error messages that can be generated by luabind, with a more in-depth explanation.

  • the attribute 'class-name.attribute-name' is read only
    

    There is no data member named attribute-name in the class class-name, or there’s no setter-function registered on that property name. See the Properties section.

  • the attribute 'class-name.attribute-name' is of type: (class-name) and does not match (class_name)
    

    This error is generated if you try to assign an attribute with a value of a type that cannot be converted to the attributes type.

  • class-name() threw an exception, class-name:function-name() threw an exception
    

    The class’ constructor or member function threw an unknown exception. Known exceptions are const char*, std::exception. See the Exceptions section.

  • no overload of 'class-name:function-name' matched the arguments (parameter-types)
    no match for function call 'function-name' with the parameters (parameter-types)
    no constructor of class-name matched the arguments (parameter-types)
    no operator operator-name matched the arguments (parameter-types)
    

    No function/operator with the given name takes the parameters you gave it. You have either misspelled the function name, or given it incorrect parameters. This error is followed by a list of possible candidate functions to help you figure out what parameter has the wrong type. If the candidate list is empty there’s no function at all with that name. See the signature matching section.

  • call of overloaded 'class-name:function-name*(*parameter-types)' is ambiguous
    ambiguous match for function call 'function-name' with the parameters (parameter-types)
    call of overloaded constructor 'class-name*(*parameter-types)' is ambiguous
    call of overloaded operator operator-name (parameter-types) is ambiguous
    

    This means that the function/operator you are trying to call has at least one other overload that matches the arguments just as good as the first overload.

  • cannot derive from C++ class 'class-name'. It does not have a wrapped type.
    

Table Of Contents

Previous topic

Splitting up the registration

Next topic

Build options