Josh Posted April 28, 2011 Share Posted April 28, 2011 Has anyone here done exception handling with LuaBind? With BlitzMax I was able to use Try/Catch to display the script line a program crashes on, but I can't get this working in C++. Below is my Lua interpreter code. This is a class that corresponds to a single Lua state, and has functions that are easier to call: The Invoke() function at the bottom is where most of the action is. #include "../le3.h" namespace le3 { Interpreter::Interpreter() : L(NULL) { L=lua_open(); luaopen_debug(L); luaL_openlibs(L); luabind::open(L); //Bind classes bind_LE3_Vec2(L); bind_LE3_Vec3(L); bind_LE3_Vec4(L); bind_LE3_AABB(L); bind_LE3_Plane(L); bind_LE3_Quat(L); bind_LE3_Mat3(L); bind_LE3_Mat4(L); bind_LE3_Transform(L); bind_LE3_Entity(L); bind_LE3_Pivot(L); //Bind global functions using namespace luabind; module(L) [ //Global functions def("Print", (void(*)(const std::string&)) &le3::Print), def("LoadModel", (Model*(*)(const std::string&, const int& flags)) &le3::LoadModel), def("GenerateError", &GenerateError), //Model class_<Model,Entity>("Model") ]; } Interpreter::~Interpreter() { if (L!=NULL) { lua_close(L); L = NULL; } } int Interpreter::GetStackSize() { return lua_gettop(L); } void Interpreter::SetStackSize(const int& size) { int currentsize = GetStackSize(); if (size<currentsize) lua_pop(L,currentsize-size); } void Interpreter::HandleError() { Print("Error: "+std::string(lua_tostring(L,-1))); } void Interpreter::HandleException() { std::string err = "Lua debugger not found."; lua_getglobal(L,"debug"); if (lua_istable(L,-1)!=0) { lua_getfield(L,-1,"traceback"); if (lua_isfunction(L,-1)!=0) { if (lua_pcall(L,0,1,0)==0) { if (lua_isstring(L,-1)!=0) { err = lua_tostring(L,-1); } } } } Print("Error: "+err); } bool Interpreter::ExecuteString(std::string& source) { bool result = false; int errorhandler = 0; int size = GetStackSize(); if (luaL_loadbuffer(L,source.c_str(),source.length(),"")==0) { result = Invoke(0,0); } else { HandleError(); } SetStackSize(size); return result; } bool Interpreter::ExecuteFile(const std::string& path) { bool result = false; int errorhandler = 0; int size = GetStackSize(); Bank* bank = LoadBank(path); if (bank==NULL) return false; if (luaL_loadbuffer(L,bank->buf,bank->GetSize(),path.c_str())==0) { result = Invoke(0,0); } else { HandleError(); } delete bank; SetStackSize(size); return result; } bool Interpreter::Invoke(const int& in, const int& out) { try { if (lua_pcall(L,in,out,0)==0) { return true; } else { HandleError(); } } catch(luabind::error& e) { HandleException(); } } } Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted April 28, 2011 Author Share Posted April 28, 2011 If I throw an exception in the try block, it gets caught. If the Lua script calls a C++ function that throws an exception, no exception is caught by the catch statement. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Canardia Posted April 28, 2011 Share Posted April 28, 2011 http://www.rasterbar.com/products/luabind/docs.html#structured-exceptions-msvc Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Josh Posted April 28, 2011 Author Share Posted April 28, 2011 How is this supposed to compile?: ::_set_se_translator(straight_to_debugger); Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 I created a project that runs a Lua script and creates an error: In "le3.cpp" the GenerateError() function will try to call a function with a null pointer: void GenerateError() { Interpreter* i = NULL; i->GetStackSize(); } The GenerateError() function is exposed via LuaBind and is called by "test.lua". I want to be able to tell what line the script was executing when the program crashes, and to be able to get all the variables and call stack within Lua for debugging purposes. The Lua script is run in the Interpreter::ExecuteFile() function, which calls Interpreter::Invoke(): bool Interpreter::ExecuteFile(const std::string& path) { bool result = false; int errorhandler = 0; int size = GetStackSize(); if (luaL_loadfile(L,path.c_str())==0) { result = Invoke(0,0); } else { HandleError(); } SetStackSize(size); return result; } bool Interpreter::Invoke(const int& in, const int& out) { try { if (lua_pcall(L,in,out,0)==0) { return true; } else { HandleError(); } } //catch (luabind::error& e) catch(...) { HandleException(); } return false; } If anyone has experience doing this with C++ any advice is appreciated. I had try/catch working with Lua and BlitzMax, but this is a bit different. I'm going to use the debug info to construct a nice debug interface in the script editor, so you can click around and see everything that's going on in the script program. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 I found if I call debug.traceback in the C++ function before the error is caused, I can show the call stack of the Lua program. However, Luabind is "eating" my exceptions so they never come back to the main program. The code on Rasterbar's site for MSVC has no effect. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Canardia Posted April 29, 2011 Share Posted April 29, 2011 You can't catch OS and hardware errors with standard C++ catches, but when you add a signal handler, you can catch all C++/OS/hardware errors: http://www.ibm.com/developerworks/linux/library/l-cppexcep.html http://stackoverflow.com/questions/457577/catching-access-violation-exceptions Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 If that's just a limitation of the OS I can live with it. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Krankzinnig Posted April 29, 2011 Share Posted April 29, 2011 try{ MakeLE2IntoLE3(); } catch(luabind::Error &YourException) { lua_State* L = e.state(); } Check your luabind errors with: lua_error() Although this isn't the only exception luabind will throw, its the most common one ;P Quote AMD Phenom II X4 B55 3.20 GHz - 8.00 GB Patriot Gamer Series RAM - AMD Radeon HD 6800 Series 1 GB GDDR5 - Windows 7 Professional 64 Bit Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 That doesn't do anything. No matter what, if I throw an exception in a C++ function Lua calls, it just prints the exception in the Lua error log, and doesn't actually throw anything for my catch statement to catch. I added that thing rasterbar said to in the main function and it has no effect. #ifdef _MSC_VER _set_se_translator(straight_to_debugger); #endif Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Krankzinnig Posted April 29, 2011 Share Posted April 29, 2011 if (lua_pcall(L,in,out,0)==0) { return true; } Quote AMD Phenom II X4 B55 3.20 GHz - 8.00 GB Patriot Gamer Series RAM - AMD Radeon HD 6800 Series 1 GB GDDR5 - Windows 7 Professional 64 Bit Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 I created a new C++ function: void RuntimeError(const std::string& error) { throw std::exception(error.c_str()); } Here is the Lua script that calls it: print("Creating an error...") RuntimeError("An error has occurred!") Here is the code that runs the script: bool Interpreter::Invoke(const int& in, const int& out) { try { if (lua_pcall(L,in,out,0)==0) { return true; } else { //If you throw an exception, it gets displayed here, which isn't what we want: HandleError(); } } //Exceptions should be getting caught here: catch(luabind::error& e) { Print("Caught the exception!"); exit(1); } return false; } Instead of catching an exception, the Lua error log just prints out "std-exception: 'An error has occurred!'" Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Krankzinnig Posted April 29, 2011 Share Posted April 29, 2011 Yeah thats working great then, now put throw in there. In your main do your main exception that catches everything. Quote AMD Phenom II X4 B55 3.20 GHz - 8.00 GB Patriot Gamer Series RAM - AMD Radeon HD 6800 Series 1 GB GDDR5 - Windows 7 Professional 64 Bit Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 That's not what's supposed to happen. LuaBind is supposed to throw a LuaBind exception my catch statement would catch. I don't want to parse the error log and guess which messages might be exceptions. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Krankzinnig Posted April 29, 2011 Share Posted April 29, 2011 I see, I know you can do custom exception handling in luabind as well. Try this: luabind::register_exception_handler<MyException>(&FunctionToCallWhenExceptionOccurs); You can also replace the luabind error text with your own and then make it actually return and stop the program maybe? My point was to do it like this: // lua class try { luacode } catch { LuaException = true; } // in any other class try { LuaClass::Init(); if(LuaClass::LuaException) { throw; } } catch(blah) { return 0; // or w/e } Its annoying, but Entity also has multiple levels of exceptions. So when I inherit these classes into my scene classes, all the exceptions forward to my engine and throws my UI notification dialog I made. Quote AMD Phenom II X4 B55 3.20 GHz - 8.00 GB Patriot Gamer Series RAM - AMD Radeon HD 6800 Series 1 GB GDDR5 - Windows 7 Professional 64 Bit Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 If any of the functions you register throws an exception when called, that exception will be caught by luabind and converted to an error string and lua_error() will be invoked. Ahhhhh, it makes sense now. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Krankzinnig Posted April 29, 2011 Share Posted April 29, 2011 Lmao this is what I was trying to say ;P Quote AMD Phenom II X4 B55 3.20 GHz - 8.00 GB Patriot Gamer Series RAM - AMD Radeon HD 6800 Series 1 GB GDDR5 - Windows 7 Professional 64 Bit Link to comment Share on other sites More sharing options...
Josh Posted April 29, 2011 Author Share Posted April 29, 2011 I don't know if it's possible to call debug.trace once an exception has been thrown, before lua_pcall returns, but it is possible to make my own RuntimeError() function which first performs a debug.trace if it is being called from a Lua state. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
TylerH Posted May 31, 2011 Share Posted May 31, 2011 I take it you just dropped LuaBind and went with toLua++ right? Quote nVidia 530M Intel Core i7 - 2.3Ghz 8GB DDR3 RAM Windows 7 Ultimate (64x)----- Visual Studio 2010 Ultimate Google Chrome Creative Suite 5 FL Studio 10 Office 15 ----- Expert Professional Expert BMX Programmer ----- Link to comment Share on other sites More sharing options...
Josh Posted May 31, 2011 Author Share Posted May 31, 2011 Yes. Object slicing with ToLua isn't an issue as long as you keep the object in Lua memory somehow, so I just add all relevant object to a global table. Quote My job is to make tools you love, with the features you want, and performance you can't live without. Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.