Drop longjmp-based exception handling approach
Using longjmp was incompatible with using C++ objects in the code using the wrappers, and using this C API from C++ to avoid ABI incompatibilities between different C++ compilers is one of the main reasons for using this module. Also, this required using a separate SwigObj instead of just using the real object pointer which inevitably resulted in memory leaks whenever a non owned object was returned from anywhere, e.g. from a member accessor or any method returning pointer or reference. Abandon the attempts to recreate C++ exceptions in C and just use a very simple approach allowing to pass an error message out of band after any function call in a global variable. An alternative could be to add a special "out" error parameter to each and every function, but this risked being too verbose, especially for the functions which don't really throw, and the calls to SWIG_PendingException_get() won't need to be made explicitly when using a C++ wrapper around the generated C API in the future. This simplifies both the module and the generated code, in particular we don't need any runtime code at all any more and there is no need for an extra level of indirection for every object. It also makes a couple more tests pass.
This commit is contained in:
parent
bda731cd8f
commit
10d25c7327
7 changed files with 92 additions and 413 deletions
|
|
@ -3,57 +3,41 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "example_wrap.h"
|
||||
|
||||
static void show_exception(const char* prefix) {
|
||||
SWIG_CException* ex = SWIG_PendingException_get();
|
||||
assert(ex);
|
||||
printf("%s exception: %s (%d)\n", prefix, SWIG_CException_msg_get(ex), SWIG_CException_code_get(ex));
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
|
||||
int main() {
|
||||
Test *t = Test_new();
|
||||
|
||||
SWIG_try {
|
||||
Test_unknown(t);
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
printf("incomplete type: %s\n", SWIG_exc.msg);
|
||||
}
|
||||
SWIG_endtry;
|
||||
Test_unknown(t);
|
||||
show_exception("Unknown");
|
||||
|
||||
SWIG_try {
|
||||
Test_simple(t);
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
printf("%s\n", SWIG_exc.msg);
|
||||
}
|
||||
SWIG_endtry;
|
||||
Test_simple(t);
|
||||
show_exception("Int");
|
||||
|
||||
SWIG_try {
|
||||
Test_message(t);
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
printf("%s\n", SWIG_exc.msg);
|
||||
}
|
||||
SWIG_endtry;
|
||||
Test_message(t);
|
||||
show_exception("String");
|
||||
|
||||
SWIG_try {
|
||||
Test_hosed(t);
|
||||
}
|
||||
SWIG_catch(Exc) {
|
||||
printf("%d %s\n", Exc_code_get(SWIG_exc.klass),
|
||||
Exc_msg_get(SWIG_exc.klass));
|
||||
}
|
||||
Test_hosed(t);
|
||||
show_exception("Custom");
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
SWIG_try {
|
||||
Test_multi(t, i);
|
||||
Test_multi(t, i);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
printf("Success for i=%d\n", i);
|
||||
} else {
|
||||
printf("For i=%d", i);
|
||||
show_exception("");
|
||||
}
|
||||
SWIG_catch(Exc) {
|
||||
printf("%d %s\n", Exc_code_get(SWIG_exc.klass),
|
||||
Exc_msg_get(SWIG_exc.klass));
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
printf("%s\n", SWIG_exc.msg);
|
||||
}
|
||||
SWIG_endtry;
|
||||
}
|
||||
|
||||
SWIG_exit(0);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ FAILING_C_TESTS := \
|
|||
lextype \
|
||||
li_carrays \
|
||||
li_cdata \
|
||||
li_constraints \
|
||||
li_cpointer \
|
||||
nested \
|
||||
nested_extend_c \
|
||||
|
|
@ -88,12 +87,10 @@ FAILING_CPP_TESTS := \
|
|||
nested_class \
|
||||
nested_scope \
|
||||
nested_template_base \
|
||||
overload_arrays \
|
||||
smart_pointer_extend \
|
||||
smart_pointer_not \
|
||||
smart_pointer_template_defaults_overload \
|
||||
struct_initialization_cpp \
|
||||
template_arg_typename \
|
||||
template_basic \
|
||||
template_default \
|
||||
template_default_class_parms_typedef \
|
||||
|
|
|
|||
|
|
@ -5,60 +5,40 @@
|
|||
int main() {
|
||||
A* a = A_new();
|
||||
|
||||
SWIG_try {
|
||||
A_foo(a);
|
||||
}
|
||||
SWIG_catch(E1) {
|
||||
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
A_foo(a);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
fprintf(stderr, "foo: bad exception order\n");
|
||||
} else {
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
SWIG_endtry;
|
||||
|
||||
SWIG_try {
|
||||
A_bar(a);
|
||||
}
|
||||
SWIG_catch(E2) {
|
||||
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
A_bar(a);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
fprintf(stderr, "bar: bad exception order\n");
|
||||
} else {
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
SWIG_endtry;
|
||||
|
||||
SWIG_try {
|
||||
A_foobar(a);
|
||||
A_foobar(a);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
fprintf(stderr, "foobar: bad exception order\n");
|
||||
} else {
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
if (strcmp(SWIG_exc.msg, "postcatch unknown") != 0) {
|
||||
fprintf(stderr, "bad exception order\n");
|
||||
SWIG_throw_msg(SWIG_exc.klass, SWIG_exc.msg);
|
||||
}
|
||||
}
|
||||
SWIG_endtry;
|
||||
|
||||
SWIG_try {
|
||||
A_barfoo(a, 1);
|
||||
}
|
||||
SWIG_catch(E1) {
|
||||
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
A_barfoo(a, 1);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
fprintf(stderr, "barfoo(1): bad exception order\n");
|
||||
} else {
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
SWIG_endtry;
|
||||
|
||||
SWIG_try {
|
||||
A_barfoo(a, 2);
|
||||
}
|
||||
SWIG_catch(E2) {
|
||||
|
||||
}
|
||||
SWIG_catch(SWIG_AnyException) {
|
||||
A_barfoo(a, 2);
|
||||
if (!SWIG_PendingException_get()) {
|
||||
fprintf(stderr, "barfoo(2): bad exception order\n");
|
||||
} else {
|
||||
SWIG_PendingException_reset();
|
||||
}
|
||||
SWIG_endtry;
|
||||
|
||||
SWIG_exit(0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue