I am wrapping the following C++ code:
// content of cpp.h
class A
{
public:
virtual int fnA() = 0;
virtual ~A() { }
};
class B
{
public:
int fnB(A &a)
{
return a.fnA();
}
};
by SWIG using the SWIG wrapper:
// content of swigmodule.i
%module(directors="1") swigmodule
%feature("director");
%feature("director:except") {
if ($error != NULL) {
fprintf(stderr, "throw\n");
throw Swig::DirectorMethodException();
}
}
%exception {
try { $action }
catch (Swig::DirectorException &e) { fprintf(stderr, "catch\n"); SWIG_fail; }
}
%{
#include "cpp.h"
%}
%include "cpp.h"
where the exception handling is copied from the SWIG manual. Using this I generated the SWIG wrapper with: "swig -c++ -python swigmodule.i; g++ -shared -fPIC -I/usr/include/python2.7 swigmodule_wrap.cxx -o _swigmodule.so"
The problem now comes when incorrectly overloading the "int fnA()" function with a "void fnA()" in Python.
# content of useit.py
from swigmodule import A, B
class myA(A):
def fnA(self):
print("myA::fnA")
b = B();
a = myA();
print("%d"% b.fnB(a) )
The generated SWIG wrapper correctly flags this at runtime as an error; fnA(self) returns None which is not an int. However, the output at the console is:
$ python useit.py
myA::fnA
catch
Traceback (most recent call last):
File "useit.py", line 12, in <module>
print("%d"% b.fnB(a) )
File "/home/schuttek/tmp/swigmodule.py", line 109, in fnB
def fnB(self, *args): return _swigmodule.B_fnB(self, *args)
TypeError: SWIG director type mismatch in output value of type 'int'
which is misleading as it suggests that the error is in B::fnB where the actual error is in overloading A::fnA.
How do I get SWIG to provide a meaningfull diagnostic to where the error occured? In my real code (this is a simplified version) I had to use GDB to trap on the constructor of the Swig::DirectorException class. This is unwanted as the actual error was in the Python domain (where an incorrect overlaod was performed) and I want to shield future Python users from GDB and its usage, as well as from a SWIG internal such as a DirectorException.
fnB
that the type mismatch is detected and rightly so. You probably could do something clever with metaclasses to spot it earlier if you really wanted though, but I'm not sure I buy it as "a big thing". - Flexo%typemap(directorout)
, using the macro%dirout_fail
to actually do it but changing globally is tricky because there are a lot of typemaps for use with directors already, so it's not just a case of tweaking one to apply everywhere. Apply for allint
or any other known return type should be simple enough though. - Flexo