Swig and Python - different object instantation
Question: I Have a question regarding swig wrapped objects generated on the Python side
and wrapped objects generated on the C++ side. Suppose I have the following
simple C++ class definitions

    
    
    #include <vector>
    
    class Sphere
    {
    public:
        Sphere(){};
    };
    
    class Container
    {
    public:
        Container() : data_(0) {};
    
        void add() {
            data_.push_back(Sphere());
        }
    
        Sphere & get(int i) { return data_[i]; }
    
        std::vector<Sphere> data_;
    };
    

and the following swig setup

    
    
    %module engine
    %{
    #define SWIG_FILE_WITH_INIT
    #include "sphere.h"
    %}
    
    // -------------------------------------------------------------------------
    // Header files that should be parsed by SWIG
    // -------------------------------------------------------------------------
    %feature("pythonprepend") Sphere::Sphere() %{
        print 'Hello'
    %}
    %include "sphere.h"
    

If I then do the following in Python

    
    
    import engine
    sphere_0 = engine.Sphere()
    container = engine.Container()
    container.add()
    sphere_1 = container.get(0)
    

Then the first instantiation of the wrapped Sphere class does call the
**init** method of the Python wrapping interface ('Hello' is printed).

However, the second, where the instance is generated on the C++ side does not
('Hello' is not printed).

Since my goal is to be able to add additional Python functionality to the
object upon its construction, I'd be pleased to hear if anybody has any
pointers for a correct approach to achieve this - for both of the above
instantiation scenarios.

Best regards,

Mads


Answer: I usually do things like this with explicit `pythoncode` blocks in the
interface file:

    
    
    %pythoncode %{
    def _special_python_member_function(self):
         print "hello"
         self.rotate() # some function of Sphere
    Sphere.new_functionality=_special_python_member_function
    %}
    

So you can add arbitrary python functionality to the class, on top of what the
SWIG interface provides. You may want/need to `rename` some of the C
functionality out the way but this can should get you all of the member
_functions_ you want.

I've never tried to remap `__init__` in this way, so I don't know how that
would behave. Assuming that it won't work, you won't be able to ensure that
the python objects have a given internal state (member variables) at
construction.

What you will be forced to do is do lazy evaluation:

    
    
    def function_that_depends_on_python_specific_state(self, *args):
       if not hasatttr( self, 'python_data'):
            self.python_data = self.make_python_data() # construct the relevant data
       pass # do work that involves the python specific data
    

and check for the existence of the python specific data. If there is just a
few cases of this, I'd just put it in the functions as above. However, if that
ends up being messy, you could modify `__getattr__` so that it constructs the
python-specific data members as they are accessed.

    
    
    def _sphere_getattr(self, name):
        if name=='python_data':
             self.__dict__[name]=self.make_python_data()
             return self.__dict__[name]
        else:
            raise AttributeError
    Sphere.__getattr__ = _sphere_getattr
    

IMHO, in the limit where you have a large amount of new functionality, and
data that are independent of the underlying C implementation, you are in
effect asking "How can I make my python Sphere class be a sub-class ofthe C
Sphere class but keep them as the same type?"

