So I'm playing about with Python, C++0x, and SWIG 2.0. I've got a header that looks like this:
#include <string>
#include <iostream>
#include <memory>
using namespace std;
struct Base {
virtual string name();
int foo;
shared_ptr<Base> mine;
Base(int);
virtual ~Base() {}
virtual void doit(shared_ptr<Base> b) {
cout << name() << " doing it to " << b->name() << endl;
mine = b;
}
virtual shared_ptr<Base> getit() {
return mine;
}
};
struct Derived : Base {
virtual string name();
int bar;
Derived(int, int);
};
Meanwhile, the interface file looks like this:
%module(directors="1") foo
%feature("director");
%include <std_string.i>
%include <std_shared_ptr.i>
%shared_ptr(Base)
%shared_ptr(Derived)
%{
#define SWIG_FILE_WITH_INIT
#include "foo.hpp"
%}
%include "foo.hpp"
My Python session then goes like this:
>>> import foo
>>> b = foo.Base(42)
>>> d = foo.Derived(23,64)
>>> b.doit(d)
Base doing it to Derived
>>> g = b.getit()
>>> g
<foo.Base; proxy of <Swig Object of type 'std::shared_ptr< Base > *' at 0x7f7bd1391930> >
>>> d
<foo.Derived; proxy of <Swig Object of type 'std::shared_ptr< Derived > *' at 0x7f7bd137ce10> >
>>> d == g
False
>>> d is g
False
>>> d.foo == g.foo
True
>>> d.bar
64
>>> g.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Base' object has no attribute 'bar'
I can't seem to figure out how to retrieve the "original" proxy object here. Must I produce a function for each and every base class to perform the dynamic_pointer_cast
? And if so, what of Director subclasses implemented in Python?
I get the feeling there's a switch or feature I can turn on here to get SWIG to do the necessary table lookups and produce the object I want, but I haven't found it yet.
(Note: The behavior is similar if I use raw pointers instead of shared pointers, and I can't figure out how to get SWIG to dynamic_cast
those either)
Update
If this sort of behavior (specifically, retrieving the most-derived proxy from a C++ container class that holds pointers to the base class) isn't possible in SWIG, then how about SIP or some other wrapper generator for Python?
Update #2
Since SIP4 looks like it works a bit better as far as retrieving the wrapped object sensibly, I'll change the question once again. Check my self answer below for details on my current issues. I'll still accept a good answer for the original SWIG question since I prefer it overall, but my new questions are, basically:
How can I deal sanely with wrappers around
shared_ptr
s rather than raw pointers? If it helps, all of my classes subclassenable_shared_from_this
from their generic base classes and expose an appropriate function to get the shared pointer.How can I, using either of SIP4's build systems (Makefile generator or distutils extension), build my little example project without having to first generate and install a shared library or manually edit the generated Makefile?