Cross language polymorphism

A cool feature would be to be able to define derived classes from the Python interface. This is already possible to some extent for Distributions and Functions (with PythonDistribution and OpenTURNSPythonFunction respectively), but could maybe be extended to other classes.

It seems to me that SWIG offers a generic way to do this with its “director” feature. See the following links:

EDIT: Thanks to Jean-Christophe Houdebine for pointing out the role of the clone() method.

So I played around with directors and was able to produce a minimal example (to get it to do something interesting much more work would be needed I suppose).

Let’s say we want to emulate what PythonDistribution does: we want to be able to define child classes of DistributionImplementation.

Step 0 : expose clone() to Python

In python/src/OTtypes.i remove the line that tells SWIG to ignore clone() methods:

%ignore *::clone() const;

Step 1 : enable directors at module level

In python/src/model_copula_module.i, replace the %module directive with:

%module(package="openturns", docstring="Copulas.", directors="1") model_copula

Step 2 : create directors for the parent class

In python/src/DistributionImplementation.i, before

%include openturns/DistributionImplementation.hxx

add the following line:

%feature("director") DistributionImplementation;

Step 3 : implement a child class that overrides the clone() method

The following Python script:

import openturns as ot

class Stupid(ot.DistributionImplementation):

    def __init__(self):
        super().__init__()

    def clone(self):
        return self
    
    def getRealization(self):
        return ot.Point([0.123])
    
s = Stupid()
print(s.getSample(3))
rv = ot.RandomVector(s)
print(rv.getRealization())
print(rv.getSample(2))

produces:

    [ X0    ]
0 : [ 0.123 ]
1 : [ 0.123 ]
2 : [ 0.123 ]
[0.123]
    [ X0   ]
0 : [ 0.123 ]
1 : [ 0.123 ]

Without directors, it would produce the following error:

RuntimeError: NotYetImplementedException : In DistributionImplementation::computeCDF(const Point & point) const

Without overriding the clone() method, this error would also be produced when getRealization() is called from the RandomVector.

I just retried, doesnt build either due to a simple syntax error, which swig version are you using ? I have 3.0.12, I guess it was fixed in 4.x

then it works, but we cannot wrap it in a Distribution object, so it means we wont be able to combine in higher level objects (Composed, RV, …), sad

@schueller Jean-Christophe Houdebine has given me a tip to make this work (see the update to my original post): the child class needs to implement clone(), which implies that this method must be exposed to Python.

He warns us that conting references might get tricky with directors.
A possible solution would be to use disown() to let C++ take care of memory alone.