Let's say I have wrapped my C++ classes Foo and Bar and can access them from Python just fine through the SWIG generated module wrap_py:
// C++
class Bar
{
int i;
Bar(int i) { this.i = i; }
}
class Foo
{
public:
Foo(Bar* bar) { this.bar = bar; }
Bar* GetBar() { return this.bar; }
private:
Bar* bar;
}
In Python, I created my user facing class that are a shallow proxy mainly adding docstrings and allowing the IDE to do tab completion on the argument names:
// Python
class Bar(wrap_py.Bar):
'''Some description ...
Args:
i (int): ...
'''
def __init__(self, i):
super(Bar, self).__init__(i)
class Foo(wrap_py.Foo):
'''Some description ...
Args:
bar (instance of Bar): ...
'''
def __init__(self, bar):
super(Foo, self).__init__(bar)
The problem is here that Foo.GetBar(), which is automatically generated from the C++ class, returns the swig instance of type wrap_py.Bar, which doesn't have the docstrings and also doesn't show the parameter names (swig exposes all parameters as *args). Instead, I would want it to provide my own shallow proxy Bar.
So, how can I tell SWIG, to automatically return Bar instead of the bare wrap_py.Bar?
EDIT: Ideally, this would be possible for the return type Bar and not only for a concrete function signature:
%feature("shadow") Foo::GetBar() %{
def bar(*args):
result = $action
result.__class__ = Bar
return result
%}
EDIT 2: I've come up with the following decorator, which I need to put in front of every function/method that returns a SWIG type:
def typemap(f):
Definitely, this is not nice and calls for omissions.
from functools import wraps
@wraps(f)
def wrapper(*args, **kwds):
typemap = {
wrap_py.Bar: Bar,
# more types to come...
}
result = f(*args, **kwds)
if isinstance(result, (tuple, list, set)):
for r in result:
r.__class__ = typemap.get(r.__class__, r.__class__)
elif isinstance(result, dict):
for k,v in result.items():
k.__class__ = typemap.get(k.__class__, k.__class__)
v.__class__ = typemap.get(v.__class__, v.__class__)
else:
result.__class__ = typemap.get(result.__class__, result.__class__)
return result
return wrapper