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:
Vadim Zeitlin 2021-11-25 01:43:25 +01:00
commit 9a8ebbb998
6 changed files with 207 additions and 37 deletions

View file

@ -5,10 +5,16 @@ CXXSRCS = example.cxx
TARGET = example
INTERFACE = example.i
check: build
check_c: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' RUNME_EXT=c c_run
check_cxx: build
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' \
TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' RUNME_EXT=cxx c_run
check: check_c check_cxx
build:
$(MAKE) -f $(TOP)/Makefile SRCDIR='$(SRCDIR)' CXXSRCS='$(CXXSRCS)' \
SWIG_LIB_DIR='$(SWIG_LIB_DIR)' SWIGEXE='$(SWIGEXE)' \

View file

@ -8,10 +8,10 @@
#include "example_wrap.h"
static void show_exception(const char* prefix) {
SWIG_CException* ex = example_SWIG_PendingException_get();
SWIG_CException* ex = SWIG_CException_get_pending();
assert(ex);
printf("%s exception: %s (%d)\n", prefix, SWIG_CException_msg_get(ex), SWIG_CException_code_get(ex));
example_SWIG_PendingException_reset();
SWIG_CException_reset_pending();
}
int main() {
@ -32,7 +32,7 @@ int main() {
int i;
for (i = 0; i < 4; ++i) {
Test_multi(t, i);
if (!example_SWIG_PendingException_get()) {
if (!SWIG_CException_get_pending()) {
printf("Success for i=%d\n", i);
} else {
printf("For i=%d", i);

View file

@ -0,0 +1,69 @@
/*
* NOTE: this won't run with -noexcept flag
*/
#include <stdio.h>
#include <assert.h>
#include "example_wrap.h"
using Exception = example::SWIG_CException;
static int exit_code = 0;
static void show_exception(const char* prefix, Exception const& ex) {
printf("%s exception: %s (%d)\n", prefix, ex.msg(), ex.code());
}
static void missing_exception(const char* prefix) {
printf("*** ERROR: %s: expected exception not thrown.\n", prefix);
exit_code++;
}
int main() {
example::Test t;
try {
t.unknown();
missing_exception("Unknown");
} catch (Exception const& e) {
show_exception("Unknown", e);
}
try {
t.simple();
missing_exception("Int");
} catch (Exception const& e) {
show_exception("Int", e);
}
try {
t.message();
missing_exception("String");
} catch (Exception const& e) {
show_exception("String", e);
}
try {
t.hosed();
missing_exception("Custom");
} catch (Exception const& e) {
show_exception("Custom", e);
}
for (int i = 0; i < 4; ++i) {
try {
t.multi(i);
if (i == 0) {
printf("Success for i=%d\n", i);
} else {
missing_exception("Multi");
}
} catch (Exception const& e) {
printf("For i=%d", i);
show_exception("", e);
}
}
return exit_code;
}