/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus * * MAUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MAUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MAUS. If not, see . * */ #include #include #include "json/json.h" #include "src/common_cpp/Utils/CppErrorHandler.hh" #include "src/common_cpp/Utils/JsonWrapper.hh" #include "Interface/Squeak.hh" namespace MAUS { CppErrorHandler* CppErrorHandler::instance = NULL; CppErrorHandler* CppErrorHandler::getInstance() { if (!instance) instance = new CppErrorHandler(); return instance; } Json::Value CppErrorHandler::HandleException (Json::Value val, Exception exc, std::string class_name) { Squeak::mout(Squeak::debug) << "Stack trace:" << exc.GetStackTrace() << std::endl; return getInstance()->ExceptionToPython(exc.what(), val, class_name); } Json::Value CppErrorHandler::HandleStdExc (Json::Value val, std::exception& exc, std::string class_name) { Json::Value out = getInstance()->ExceptionToPython((&exc)->what(), val, class_name); return out; } void CppErrorHandler::HandleExceptionNoJson(Exception exc, std::string class_name) { Json::Value json = Json::Value(); HandleException(json, exc, class_name); } void CppErrorHandler::HandleStdExcNoJson (std::exception& exc, std::string class_name) { Json::Value json = Json::Value(); HandleStdExc(json, exc, class_name); } Json::Value CppErrorHandler::ExceptionToPython (std::string what, Json::Value json_value, std::string class_name) { // Logic is: // * Make sure the Python error handler is loaded // * Clear any existing exceptions // * Make json_value into a string // * Hand json_value, class name, description of error to python // * Convert return PyObject to string // * Convert string to json value PyErr_Clear(); // clear any existing exceptions Json::FastWriter writer; std::string json_in_cpp = writer.write(json_value); char* sss = const_cast("sss"); // gotta love C (dodge compiler warning) PyObject* error_handler_function = GetPyErrorHandler(); PyObject* json_out_py = PyObject_CallFunction // call the Python ErrorHandler (error_handler_function, sss, json_in_cpp.c_str(), class_name.c_str(), what.c_str()); Py_DECREF(error_handler_function); const char* json_str; if (!json_out_py) { // python ErrorHandler was set to raise the error Squeak::mout(Squeak::error) << "ERROR: Failed to handle error:" << std::endl; PyErr_Print(); throw std::exception(); } int ok = PyArg_Parse(json_out_py, "s", &json_str); // convert to string if (!ok) { // we didn't get a string back Squeak::mout(Squeak::error) << "ERROR: Failed to parse return value from error:" << std::endl; PyErr_Print(); return Json::Value(); } Json::Value json_out_cpp = JsonWrapper::StringToJson(std::string(json_str)); return json_out_cpp; } CppErrorHandler::CppErrorHandler() { } PyObject* CppErrorHandler::GetPyErrorHandler() { // import ErrorHandler PyObject* py_error_handler_module = PyImport_ImportModule("ErrorHandler"); if (!py_error_handler_module) { throw Exception(Exception::recoverable, "Failed to import ErrorHandler module", "CppErrorHandler::GetPyErrorHandler"); } // ErrorHandler.getattr("HandleCppException") PyObject* handle_error_fnc = PyObject_GetAttrString(py_error_handler_module, "HandleCppException"); Py_DECREF(py_error_handler_module); if (!PyCallable_Check(handle_error_fnc)) throw Exception(Exception::recoverable, "Failed to get HandleCppException function", "CppErrorHandler::GetPyErrorHandler"); return handle_error_fnc; } CppErrorHandler::~CppErrorHandler() { instance = NULL; } } // namespace MAUS