/* 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; Json::Value CppErrorHandler::HandleSqueal (Json::Value val, Squeal 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) { return getInstance()->ExceptionToPython((&exc)->what(), val, class_name); } void CppErrorHandler::HandleSquealNoJson(Squeal exc, std::string class_name) { HandleSqueal(Json::Value(), exc, class_name); } void CppErrorHandler::HandleStdExcNoJson (std::exception& exc, std::string class_name) { HandleStdExc(Json::Value(), 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 if (!getInstance()->GetPyErrorHandler()) { // Importing ErrorHandler calls libMausCpp which calls SetPyErrorHandler std::cerr << "Not GetInstance" << std::endl; PyImport_ImportModule("ErrorHandler"); PyErr_Clear(); if (CppErrorHandler::getInstance()->GetPyErrorHandler() == 0) { Squeak::mout(Squeak::error) << "ERROR: Failed to get python error handler" << std::endl; } } PyErr_Clear(); // clear any existing exceptions Json::FastWriter writer; std::string json_in_cpp = writer.write(json_value); char sss[4] = {'s', 's', 's', '\0'}; // gotta love C (dodge compiler warning) PyObject* json_out_py = PyObject_CallFunction // call the Python ErrorHandler (getInstance()->GetPyErrorHandler(), &sss[0], json_in_cpp.c_str(), class_name.c_str(), what.c_str()); 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() : HandleExceptionFunction(NULL) { } CppErrorHandler* CppErrorHandler::getInstance() { if (instance == NULL) { // Don't initialise PyErrorHandler here - because we can get caught up in // initalisation order issues instance = new CppErrorHandler(); Py_Initialize(); } return instance; } CppErrorHandler::~CppErrorHandler() { instance = NULL; } } // namespace MAUS