From: Jörg F. U. <joe...@un...> - 2009-06-24 14:15:11
|
I'm trying to build a C++ library doing the complex mathematics with a Python interpreter on top of it. In the application it occasionally occurs that exceptions are thrown. I'd like to catch these exceptions in Python, but a really would like to catch not the standard exceptions, but my own exception written in c++ and - via swig - wrapped to a Python exception. This is illustrated for a small example. I've got a class Matrix with a setValue method. If the position is out of the range of the allocated memory of the matrix, an exception of the type MyException is thrown. //File Matrix.h #ifndef MATRIX_H #define MATRIX_H #include <vector> #include "MyException.h" class Matrix { public: Matrix(int numRows_, int numColumns_, std::vector<double> entries_) { int numEntries = numRows_ * numColumns_; if (numEntries!=entries_.size()) throw MyException(std::string("Size of vector does not correspond to number of rows/colums\n")); entries = entries_; numRows = numRows_; numColumns = numColumns_; } void setValue(int row_, int col_, double value) { if (row_<0 || col_<0 || row_>=numRows || col_>=numColumns) { throw MyException(std::string("Position out of matrix dimension.")); } else entries[col_*numRows+row_] = value; } protected: int numRows, numColumns; std::vector<double> entries; }; #endif // MATRIX_H //File MyException.h #ifndef MYEXCEPTION_H #define MYEXCEPTION_H #include <string> #include <exception> class MyException : public std::exception { protected: std::string message; public: explicit MyException(const std::string& m) : message(m) {} virtual ~MyException() throw() {} virtual const char* what() const throw() { return message.c_str(); } }; #endif // MYEXCEPTION_H Using swig, I've created the wrapper files using the MyProject.i to create the module MyProject //file MyProject.i %module MyProject %{ /* Put headers and other declarations here */ #include "Matrix.h" #include "MyException.h" %} // user std::vectors on python level %include "std_vector.i" %include "std_string.i" // Instantiate templates used by example namespace std { %template(DoubleVector) vector<double>; } %include "MyException.h" %include "exception.i" %exception { try { $action } catch (MyException) { SWIG_exception_fail(SWIG_ValueError, "MyException"); } SWIG_CATCH_STDEXCEPT // catch std::exception catch (...) { SWIG_exception_fail(SWIG_UnknownError, "Unknown exception"); } } // provide the public interface %include "Matrix.h" Finally, I've applied this in a Python routine test.py //file test.py import MyProject doubleentries = MyProject.DoubleVector(0) doubleentries.resize(4) doubleentries[0] = 1 doubleentries[1] = 2 doubleentries[2] = 3 doubleentries[3] = 4.5 a=MyProject.Matrix(2,2,doubleentries) try: a.setValue(-1,-1,-1e12) except MyProject.MyException as e: print e print "That was MyException" except ValueError as e: print e print "That was a Value Error" except : print "Ohh, some undefined Error occured" What actually happens in the MyProject.i is, that the MyException is catched from the c++ file and swig creates a ValueError-exception, but instead of passing a ValueError-exception (or any other standard exception) to Python, I'd like to pass directly Myexception to Python. Myexception is via SWIG already a data type known in Python, but how can a actually modify the line catch (MyException) { SWIG_exception_fail(SWIG_ValueError, "MyException"); } to something like catch (MyException) { SWIG_exception_fail(SWIG_MyException "MyException"); } Thanks for the help Jörg F. |