From 7cb42f4368e873e5930cf84bc2494a8e8172a046 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Tue, 5 Jun 2018 21:03:06 +0200 Subject: Initial GUI work --- common/handle_error.cc | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++ common/pybindings.cc | 42 +++++++++++++++++++++++++++++++++++++ common/pybindings.h | 3 +++ common/version.h.in | 6 ++++++ 4 files changed, 107 insertions(+) create mode 100644 common/handle_error.cc create mode 100644 common/version.h.in (limited to 'common') diff --git a/common/handle_error.cc b/common/handle_error.cc new file mode 100644 index 00000000..a06b5348 --- /dev/null +++ b/common/handle_error.cc @@ -0,0 +1,56 @@ +#include +#include + +namespace py = boost::python; + +// Parses the value of the active python exception +// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION +std::string parse_python_exception(){ + PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL; + // Fetch the exception info from the Python C API + PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); + + // Fallback error + std::string ret("Unfetchable Python error"); + // If the fetch got a type pointer, parse the type into the exception string + if(type_ptr != NULL){ + py::handle<> h_type(type_ptr); + py::str type_pstr(h_type); + // Extract the string from the boost::python object + py::extract e_type_pstr(type_pstr); + // If a valid string extraction is available, use it + // otherwise use fallback + if(e_type_pstr.check()) + ret = e_type_pstr(); + else + ret = "Unknown exception type"; + } + // Do the same for the exception value (the stringification of the exception) + if(value_ptr != NULL){ + py::handle<> h_val(value_ptr); + py::str a(h_val); + py::extract returned(a); + if(returned.check()) + ret += ": " + returned(); + else + ret += std::string(": Unparseable Python error: "); + } + // Parse lines from the traceback using the Python traceback module + if(traceback_ptr != NULL){ + py::handle<> h_tb(traceback_ptr); + // Load the traceback module and the format_tb function + py::object tb(py::import("traceback")); + py::object fmt_tb(tb.attr("format_tb")); + // Call format_tb to get a list of traceback strings + py::object tb_list(fmt_tb(h_tb)); + // Join the traceback strings into a single string + py::object tb_str(py::str("\n").join(tb_list)); + // Extract the string, check the extraction, and fallback in necessary + py::extract returned(tb_str); + if(returned.check()) + ret += ": " + returned(); + else + ret += std::string(": Unparseable Python traceback"); + } + return ret; +} diff --git a/common/pybindings.cc b/common/pybindings.cc index 8bae4e51..4986c549 100644 --- a/common/pybindings.cc +++ b/common/pybindings.cc @@ -18,6 +18,7 @@ * */ + #include "design.h" #include "chip.h" #include "pybindings.h" @@ -26,6 +27,9 @@ #define PASTER(x, y) x ## _ ## y #define EVALUATOR(x, y) PASTER(x,y) #define MODULE_NAME EVALUATOR(nextpnrpy, ARCHNAME) +#define PYINIT_MODULE_NAME EVALUATOR(&PyInit_nextpnrpy, ARCHNAME) +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) // Architecture-specific bindings should be created in the below function, which must be implemented in all // architectures @@ -39,3 +43,41 @@ BOOST_PYTHON_MODULE (MODULE_NAME) { arch_wrap_python(); } + +void arch_appendinittab() +{ + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); +} + +void execute_python_file(const char *executable, const char* python_file) +{ + wchar_t *program = Py_DecodeLocale(executable, NULL); + if (program == NULL) { + fprintf(stderr, "Fatal error: cannot decode executable filename\n"); + exit(1); + } + try + { + PyImport_AppendInittab(TOSTRING(MODULE_NAME), PYINIT_MODULE_NAME); + Py_SetProgramName(program); + Py_Initialize(); + + FILE* fp = fopen(python_file, "r"); + if (fp == NULL) { + fprintf(stderr, "Fatal error: file not found %s\n",python_file); + exit(1); + } + PyRun_SimpleFile(fp , python_file); + fclose(fp); + + Py_Finalize(); + PyMem_RawFree(program); + } + catch(boost::python::error_already_set const &) + { + // Parse and output the exception + std::string perror_str = parse_python_exception(); + std::cout << "Error in Python: " << perror_str << std::endl; + } +} + diff --git a/common/pybindings.h b/common/pybindings.h index eab2039d..f594784c 100644 --- a/common/pybindings.h +++ b/common/pybindings.h @@ -79,5 +79,8 @@ struct range_wrapper { #define WRAP_RANGE(t) range_wrapper().wrap(#t "Range", #t "Iterator") +void execute_python_file(const char *executable, const char* python_file); +std::string parse_python_exception(); +void arch_appendinittab(); #endif /* end of include guard: COMMON_PYBINDINGS_HH */ diff --git a/common/version.h.in b/common/version.h.in new file mode 100644 index 00000000..8072116b --- /dev/null +++ b/common/version.h.in @@ -0,0 +1,6 @@ +#ifndef VERSION_H +#define VERSION_H + +#define GIT_COMMIT_HASH_STR "@GIT_COMMIT_HASH@" + +#endif \ No newline at end of file -- cgit v1.2.3