Throw SWIG_CException from C++ wrappers automatically
Check for the pending exception after every call to a wrapper function not marked "noexcept" and throw a C++ exception if necessary. Add C++ version of the exception example to show how this works. Also change SWIG_CException to use member functions for checking for and resetting pending exceptions, this seems better than having separate functions for it and will make it easier to customize exception handling later by just replacing SWIG_CException class with something else. Note that we still use a global (and not a member) function for raising the exception, but this one is not exported at all, and needs to be a function in order to be easily callable from other modules (see the upcoming commit).
This commit is contained in:
parent
52f8412a46
commit
9a8ebbb998
6 changed files with 207 additions and 37 deletions
|
|
@ -4,39 +4,58 @@
|
|||
* Exception handling code and typemaps for C module.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
%ignore SWIG_CException::SWIG_CException;
|
||||
// This function is special: it's used by various typemaps (via SWIG_exception
|
||||
// macro below) and needs to be defined, but we don't want to export it.
|
||||
%ignore SWIG_CException_Raise;
|
||||
%{
|
||||
extern "C" void SWIG_CException_Raise(int code, const char* msg);
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
class SWIG_CException {
|
||||
public:
|
||||
SWIG_CException(int code, const char* msg) : code(code), msg(strdup(msg)) { }
|
||||
SWIG_CException(const SWIG_CException& ex) throw() : code(ex.code), msg(strdup(ex.msg)) { }
|
||||
|
||||
const int code;
|
||||
const char* const msg;
|
||||
|
||||
private:
|
||||
friend void SWIG_PendingException_reset();
|
||||
static SWIG_CException* get_pending() throw() {
|
||||
return PendingException;
|
||||
}
|
||||
|
||||
static void reset_pending() throw() {
|
||||
if (PendingException) {
|
||||
delete PendingException;
|
||||
PendingException = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend void SWIG_CException_Raise(int code, const char* msg);
|
||||
|
||||
static SWIG_CException* PendingException;
|
||||
|
||||
SWIG_CException(int code, const char* msg) : code(code), msg(strdup(msg)) { }
|
||||
~SWIG_CException() { free(const_cast<char*>(msg)); }
|
||||
|
||||
SWIG_CException(const SWIG_CException& ex);
|
||||
SWIG_CException& operator=(const SWIG_CException& ex);
|
||||
};
|
||||
%}
|
||||
|
||||
static SWIG_CException *SWIG_PendingException = 0;
|
||||
inline SWIG_CException* SWIG_PendingException_get() { return SWIG_PendingException; }
|
||||
inline void SWIG_PendingException_reset() {
|
||||
if (SWIG_PendingException) {
|
||||
delete SWIG_PendingException;
|
||||
SWIG_PendingException = 0;
|
||||
}
|
||||
// This part is implementation only and doesn't need to be seen by SWIG.
|
||||
%{
|
||||
SWIG_CException *SWIG_CException::PendingException = 0;
|
||||
|
||||
SWIGEXPORTC void SWIG_CException_Raise(int code, const char* msg) {
|
||||
delete SWIG_CException::PendingException;
|
||||
SWIG_CException::PendingException = new SWIG_CException(code, msg);
|
||||
}
|
||||
%}
|
||||
|
||||
%insert("runtime") "swigerrors.swg"
|
||||
|
||||
#define SWIG_exception(code, msg)\
|
||||
SWIG_PendingException = new SWIG_CException(code, msg)
|
||||
SWIG_CException_Raise(code, msg)
|
||||
|
||||
%typemap(throws, noblock="1") char *, const char * {
|
||||
SWIG_exception(SWIG_RuntimeError, $1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue