diff --git a/doc/c_cpp_api.rst b/doc/c_cpp_api.rst
index b5c37a3014584109b417be00d24cccd7de80735a..0d702f7d121ffddde2f269ce5f6f1bd4e7e7b657 100644
--- a/doc/c_cpp_api.rst
+++ b/doc/c_cpp_api.rst
@@ -74,6 +74,14 @@ Activation Functors
    Returns ``1`` if it is, and ``0`` otherwise.
 
 
+.. cpp:function:: PyObject* PyBobLearnActivation_NewFromActivation(boost::shared_ptr<bob::machine::Activation> a)
+
+   Constructs a new :c:type:`PyBobLearnActivationObject` starting from a shared
+   pointer to a pre-allocated `bob::machine::Activation` instance. This API is
+   available so that return values from actuall C++ machines can be mapped into
+   Python. It is the sole way to build an object of type :py:class:`Activation`
+   without recurring to the derived classes.
+
 .. note::
 
    Other object definitions exist for each of the specializations for
diff --git a/xbob/learn/activation/activation.cpp b/xbob/learn/activation/activation.cpp
index df0b413dfd90e8406b75705d671a707bbad3cf5e..7829bddc76d373325820ab3eb9d79367eef3d693 100644
--- a/xbob/learn/activation/activation.cpp
+++ b/xbob/learn/activation/activation.cpp
@@ -43,10 +43,41 @@ PyDoc_STRVAR(s_activation_doc,
 \n\
 ");
 
+static PyObject* PyBobLearnActivation_new
+(PyTypeObject* type, PyObject*, PyObject*) {
+
+  /* Allocates the python object itself */
+  PyBobLearnActivationObject* self =
+    (PyBobLearnActivationObject*)type->tp_alloc(type, 0);
+
+  self->cxx.reset();
+
+  return reinterpret_cast<PyObject*>(self);
+
+}
+
+PyObject* PyBobLearnActivation_NewFromActivation
+(boost::shared_ptr<bob::machine::Activation> a) {
+
+  PyBobLearnActivationObject* retval = (PyBobLearnActivationObject*)PyBobLearnActivation_new(&PyBobLearnActivation_Type, 0, 0);
+
+  retval->cxx = a;
+
+  return reinterpret_cast<PyObject*>(retval);
+
+}
+
+static void PyBobLearnActivation_delete (PyBobLearnActivationObject* self) {
+
+  self->cxx.reset();
+  self->ob_type->tp_free((PyObject*)self);
+
+}
+
 static int PyBobLearnActivation_init(PyBobLearnActivationObject* self,
     PyObject*, PyObject*) {
 
-  PyErr_Format(PyExc_NotImplementedError, "cannot initialize object of base type `%s' - use one of the inherited classes", s_activation_str);
+  PyErr_Format(PyExc_NotImplementedError, "cannot initialize object of base type `%s' - use one of the inherited classes", self->ob_type->tp_name);
   return -1;
 
 }
@@ -99,7 +130,7 @@ static int apply(boost::function<double (double)> function,
 
 }
 
-static PyObject* PyBobLearnActivation_call1(PyBobLearnActivationObject* o,
+static PyObject* PyBobLearnActivation_call1(PyBobLearnActivationObject* self,
     double (bob::machine::Activation::*method) (double) const,
     PyObject* args, PyObject* kwds) {
 
@@ -120,12 +151,12 @@ static PyObject* PyBobLearnActivation_call1(PyBobLearnActivationObject* o,
     auto z_converted_ = make_safe(z_converted);
 
     if (z_converted->type_num != NPY_FLOAT64) {
-      PyErr_SetString(PyExc_TypeError, "Activation function only supports 64-bit float arrays for input array `z'");
+      PyErr_Format(PyExc_TypeError, "`%s' function only supports 64-bit float arrays for input array `z'", self->ob_type->tp_name);
       return 0;
     }
 
     if (z_converted->ndim < 1 || z_converted->ndim > 4) {
-      PyErr_Format(PyExc_TypeError, "Activation function only accepts 1, 2, 3 or 4-dimensional arrays (not %" PY_FORMAT_SIZE_T "dD arrays)", z_converted->ndim);
+      PyErr_Format(PyExc_TypeError, "`%s' function only accepts 1, 2, 3 or 4-dimensional arrays (not %" PY_FORMAT_SIZE_T "dD arrays)", self->ob_type->tp_name, z_converted->ndim);
       return 0;
     }
 
@@ -135,11 +166,11 @@ static PyObject* PyBobLearnActivation_call1(PyBobLearnActivationObject* o,
     auto res_ = make_safe(res);
 
     // processes the data
-    int ok = apply(boost::bind(method, o->base, _1),
+    int ok = apply(boost::bind(method, self->cxx, _1),
         z_converted, reinterpret_cast<PyBlitzArrayObject*>(res));
 
     if (!ok) {
-      PyErr_SetString(PyExc_RuntimeError, "unexpected error occurred applying C++ activation function to input array (DEBUG ME)");
+      PyErr_Format(PyExc_RuntimeError, "unexpected error occurred applying `%s' to input array (DEBUG ME)", self->ob_type->tp_name);
       return 0;
     }
 
@@ -152,18 +183,18 @@ static PyObject* PyBobLearnActivation_call1(PyBobLearnActivationObject* o,
 
     PyObject* z_float = PyNumber_Float(z);
     auto z_float_ = make_safe(z_float);
-    auto bound_method = boost::bind(method, o->base, _1);
+    auto bound_method = boost::bind(method, self->cxx, _1);
     double res_c = bound_method(PyFloat_AsDouble(z_float));
     return PyFloat_FromDouble(res_c);
 
   }
 
-  PyErr_Format(PyExc_TypeError, "Activation function is not capable to process input objects of type `%s'", z->ob_type->tp_name);
+  PyErr_Format(PyExc_TypeError, "`%s' is not capable to process input objects of type `%s'", self->ob_type->tp_name, z->ob_type->tp_name);
   return 0;
 
 }
 
-static PyObject* PyBobLearnActivation_call2(PyBobLearnActivationObject* o,
+static PyObject* PyBobLearnActivation_call2(PyBobLearnActivationObject* self,
     double (bob::machine::Activation::*method) (double) const,
     PyObject* args, PyObject* kwds) {
 
@@ -184,17 +215,17 @@ static PyObject* PyBobLearnActivation_call2(PyBobLearnActivationObject* o,
   auto res_ = make_safe(res);
 
   if (z->type_num != NPY_FLOAT64) {
-    PyErr_SetString(PyExc_TypeError, "Activation function only supports 64-bit float arrays for input array `z'");
+    PyErr_Format(PyExc_TypeError, "`%s' function only supports 64-bit float arrays for input array `z'", self->ob_type->tp_name);
     return 0;
   }
 
   if (res->type_num != NPY_FLOAT64) {
-    PyErr_SetString(PyExc_TypeError, "Activation function only supports 64-bit float arrays for output array `res'");
+    PyErr_Format(PyExc_TypeError, "`%s' function only supports 64-bit float arrays for output array `res'", self->ob_type->tp_name);
     return 0;
   }
 
   if (z->ndim < 1 || z->ndim > 4) {
-    PyErr_Format(PyExc_TypeError, "Activation function only accepts 1, 2, 3 or 4-dimensional arrays (not %" PY_FORMAT_SIZE_T "dD arrays)", z->ndim);
+    PyErr_Format(PyExc_TypeError, "`%s' function only accepts 1, 2, 3 or 4-dimensional arrays (not %" PY_FORMAT_SIZE_T "dD arrays)", self->ob_type->tp_name, z->ndim);
     return 0;
   }
 
@@ -213,10 +244,10 @@ static PyObject* PyBobLearnActivation_call2(PyBobLearnActivationObject* o,
   }
 
   //at this point all checks are done, we can proceed into calling C++
-  int ok = apply(boost::bind(method, o->base, _1), z, res);
+  int ok = apply(boost::bind(method, self->cxx, _1), z, res);
 
   if (!ok) {
-    PyErr_SetString(PyExc_RuntimeError, "unexpected error occurred applying C++ activation function to input array (DEBUG ME)");
+    PyErr_Format(PyExc_RuntimeError, "unexpected error occurred applying C++ `%s' to input array (DEBUG ME)", self->ob_type->tp_name);
     return 0;
   }
 
@@ -249,7 +280,7 @@ error otherwise.\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_call(PyBobLearnActivationObject* o,
+static PyObject* PyBobLearnActivation_call(PyBobLearnActivationObject* self,
   PyObject* args, PyObject* kwds) {
 
   Py_ssize_t nargs = args?PyTuple_Size(args):0 + kwds?PyDict_Size(kwds):0;
@@ -258,12 +289,12 @@ static PyObject* PyBobLearnActivation_call(PyBobLearnActivationObject* o,
 
     case 1:
       return PyBobLearnActivation_call1
-        (o, &bob::machine::Activation::f, args, kwds);
+        (self, &bob::machine::Activation::f, args, kwds);
       break;
 
     case 2:
       return PyBobLearnActivation_call2
-        (o, &bob::machine::Activation::f, args, kwds);
+        (self, &bob::machine::Activation::f, args, kwds);
       break;
 
     default:
@@ -301,7 +332,7 @@ error otherwise.\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_f_prime(PyBobLearnActivationObject* o,
+static PyObject* PyBobLearnActivation_f_prime(PyBobLearnActivationObject* self,
   PyObject* args, PyObject* kwds) {
 
   Py_ssize_t nargs = args?PyTuple_Size(args):0 + kwds?PyDict_Size(kwds):0;
@@ -310,12 +341,12 @@ static PyObject* PyBobLearnActivation_f_prime(PyBobLearnActivationObject* o,
 
     case 1:
       return PyBobLearnActivation_call1
-        (o, &bob::machine::Activation::f_prime, args, kwds);
+        (self, &bob::machine::Activation::f_prime, args, kwds);
       break;
 
     case 2:
       return PyBobLearnActivation_call2
-        (o, &bob::machine::Activation::f_prime, args, kwds);
+        (self, &bob::machine::Activation::f_prime, args, kwds);
       break;
 
     default:
@@ -353,8 +384,8 @@ error otherwise.\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_f_prime_from_f(PyBobLearnActivationObject* o,
-  PyObject* args, PyObject* kwds) {
+static PyObject* PyBobLearnActivation_f_prime_from_f
+(PyBobLearnActivationObject* self, PyObject* args, PyObject* kwds) {
 
   Py_ssize_t nargs = args?PyTuple_Size(args):0 + kwds?PyDict_Size(kwds):0;
 
@@ -362,12 +393,12 @@ static PyObject* PyBobLearnActivation_f_prime_from_f(PyBobLearnActivationObject*
 
     case 1:
       return PyBobLearnActivation_call1
-        (o, &bob::machine::Activation::f_prime_from_f, args, kwds);
+        (self, &bob::machine::Activation::f_prime_from_f, args, kwds);
       break;
 
     case 2:
       return PyBobLearnActivation_call2
-        (o, &bob::machine::Activation::f_prime_from_f, args, kwds);
+        (self, &bob::machine::Activation::f_prime_from_f, args, kwds);
       break;
 
     default:
@@ -389,8 +420,9 @@ in connection with the Activation registry.\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_UniqueIdentifier (PyBobLearnActivationObject* o) {
-  return Py_BuildValue("s", o->base->unique_identifier().c_str());
+static PyObject* PyBobLearnActivation_UniqueIdentifier
+(PyBobLearnActivationObject* self) {
+  return Py_BuildValue("s", self->cxx->unique_identifier().c_str());
 }
 
 PyDoc_STRVAR(s_load_str, "load");
@@ -401,18 +433,18 @@ Loads itself from a :py:class:`xbob.io.HDF5File`\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_Load(PyBobLearnActivationObject* o,
+static PyObject* PyBobLearnActivation_Load(PyBobLearnActivationObject* self,
     PyObject* f) {
 
   if (!PyBobIoHDF5File_Check(f)) {
-    PyErr_Format(PyExc_TypeError, "Activation function cannot load itself from `%s', only from an HDF5 file", f->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "`%s' cannot load itself from `%s', only from an HDF5 file", self->ob_type->tp_name, f->ob_type->tp_name);
     return 0;
   }
 
   auto h5f = reinterpret_cast<PyBobIoHDF5FileObject*>(f);
 
   try {
-    o->base->load(*h5f->f);
+    self->cxx->load(*h5f->f);
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
@@ -431,22 +463,22 @@ PyDoc_STRVAR(s_save_str, "save");
 PyDoc_STRVAR(s_save_doc,
 "o.save(f) -> None\n\
 \n\
-Loads itself from a :py:class:`xbob.io.HDF5File`\n\
+Saves itself to a :py:class:`xbob.io.HDF5File`\n\
 \n\
 ");
 
-static PyObject* PyBobLearnActivation_Save(PyBobLearnActivationObject* o,
-    PyObject* f) {
+static PyObject* PyBobLearnActivation_Save
+(PyBobLearnActivationObject* self, PyObject* f) {
 
   if (!PyBobIoHDF5File_Check(f)) {
-    PyErr_Format(PyExc_TypeError, "Activation function cannot write itself to `%s', only to an HDF5 file", f->ob_type->tp_name);
+    PyErr_Format(PyExc_TypeError, "`%s' cannot write itself to `%s', only to an HDF5 file", self->ob_type->tp_name, f->ob_type->tp_name);
     return 0;
   }
 
   auto h5f = reinterpret_cast<PyBobIoHDF5FileObject*>(f);
 
   try {
-    o->base->save(*h5f->f);
+    self->cxx->save(*h5f->f);
   }
   catch (std::exception& e) {
     PyErr_SetString(PyExc_RuntimeError, e.what());
@@ -509,7 +541,7 @@ static PyObject* PyBobLearnActivation_RichCompare (PyBobLearnActivationObject* s
 
   if (!PyBobLearnActivation_Check(other)) {
     PyErr_Format(PyExc_TypeError, "cannot compare `%s' with `%s'",
-        s_activation_str, other->ob_type->tp_name);
+        self->ob_type->tp_name, other->ob_type->tp_name);
     return 0;
   }
 
@@ -517,11 +549,11 @@ static PyObject* PyBobLearnActivation_RichCompare (PyBobLearnActivationObject* s
 
   switch (op) {
     case Py_EQ:
-      if (self->base->str() == other_->base->str()) Py_RETURN_TRUE;
+      if (self->cxx->str() == other_->cxx->str()) Py_RETURN_TRUE;
       Py_RETURN_FALSE;
       break;
     case Py_NE:
-      if (self->base->str() != other_->base->str()) Py_RETURN_TRUE;
+      if (self->cxx->str() != other_->cxx->str()) Py_RETURN_TRUE;
       Py_RETURN_FALSE;
       break;
     default:
@@ -531,8 +563,8 @@ static PyObject* PyBobLearnActivation_RichCompare (PyBobLearnActivationObject* s
 
 }
 
-static PyObject* PyBobLearnActivation_Str (PyBobLearnActivationObject* o) {
-  return Py_BuildValue("s", o->base->str().c_str());
+static PyObject* PyBobLearnActivation_Str (PyBobLearnActivationObject* self) {
+  return Py_BuildValue("s", self->cxx->str().c_str());
 }
 
 PyTypeObject PyBobLearnActivation_Type = {
@@ -541,7 +573,7 @@ PyTypeObject PyBobLearnActivation_Type = {
     s_activation_str,                               /* tp_name */
     sizeof(PyBobLearnActivationObject),             /* tp_basicsize */
     0,                                              /* tp_itemsize */
-    0,                                              /* tp_dealloc */
+    (destructor)PyBobLearnActivation_delete,        /* tp_dealloc */
     0,                                              /* tp_print */
     0,                                              /* tp_getattr */
     0,                                              /* tp_setattr */
@@ -574,5 +606,5 @@ PyTypeObject PyBobLearnActivation_Type = {
     0,                                              /* tp_dictoffset */
     (initproc)PyBobLearnActivation_init,            /* tp_init */
     0,                                              /* tp_alloc */
-    0,                                              /* tp_new */
+    PyBobLearnActivation_new                        /* tp_new */
 };
diff --git a/xbob/learn/activation/identity.cpp b/xbob/learn/activation/identity.cpp
index 32072b01b891166a19196921958b8280a8e80275..0463d42b3bc8d27fd19a7c915f66d367d298a188 100644
--- a/xbob/learn/activation/identity.cpp
+++ b/xbob/learn/activation/identity.cpp
@@ -28,7 +28,7 @@ static int PyBobLearnIdentityActivation_init
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return -1;
 
   try {
-    self->base = new bob::machine::IdentityActivation();
+    self->cxx.reset(new bob::machine::IdentityActivation());
   }
   catch (std::exception& ex) {
     PyErr_SetString(PyExc_RuntimeError, ex.what());
@@ -37,7 +37,7 @@ static int PyBobLearnIdentityActivation_init
     PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_identityactivation_str);
   }
 
-  self->parent.base = self->base;
+  self->parent.cxx = self->cxx;
 
   if (PyErr_Occurred()) return -1;
 
@@ -48,9 +48,8 @@ static int PyBobLearnIdentityActivation_init
 static void PyBobLearnIdentityActivation_delete
 (PyBobLearnIdentityActivationObject* self) {
 
-  delete self->base;
-  self->parent.base = 0;
-  self->base = 0;
+  self->parent.cxx.reset();
+  self->cxx.reset();
   self->parent.ob_type->tp_free((PyObject*)self);
 
 }
diff --git a/xbob/learn/activation/include/xbob.learn.activation/api.h b/xbob/learn/activation/include/xbob.learn.activation/api.h
index c737cb2d0991983563d04f0e82a8eaa5602c3545..34383078ed135819abae27ba3d73223eff282bd7 100644
--- a/xbob/learn/activation/include/xbob.learn.activation/api.h
+++ b/xbob/learn/activation/include/xbob.learn.activation/api.h
@@ -33,7 +33,7 @@
 
 typedef struct {
   PyObject_HEAD
-  bob::machine::Activation* base;
+  boost::shared_ptr<bob::machine::Activation> cxx;
 } PyBobLearnActivationObject;
 
 #define PyBobLearnActivation_Type_NUM 1
@@ -43,16 +43,20 @@ typedef struct {
 #define PyBobLearnActivation_Check_RET int
 #define PyBobLearnActivation_Check_PROTO (PyObject* o)
 
+#define PyBobLearnActivation_NewFromActivation_NUM 3
+#define PyBobLearnActivation_NewFromActivation_RET PyObject*
+#define PyBobLearnActivation_NewFromActivation_PROTO (boost::shared_ptr<bob::machine::Activation> a)
+
 /***********************************************
  * Bindings for xbob.learn.activation.Identity *
  ***********************************************/
 
 typedef struct {
   PyBobLearnActivationObject parent;
-  bob::machine::IdentityActivation* base;
+  boost::shared_ptr<bob::machine::IdentityActivation> cxx;
 } PyBobLearnIdentityActivationObject;
 
-#define PyBobLearnIdentityActivation_Type_NUM 3
+#define PyBobLearnIdentityActivation_Type_NUM 4
 #define PyBobLearnIdentityActivation_Type_TYPE PyTypeObject
 
 /*********************************************
@@ -61,10 +65,10 @@ typedef struct {
 
 typedef struct {
   PyBobLearnActivationObject parent;
-  bob::machine::LinearActivation* base;
+  boost::shared_ptr<bob::machine::LinearActivation> cxx;
 } PyBobLearnLinearActivationObject;
 
-#define PyBobLearnLinearActivation_Type_NUM 4
+#define PyBobLearnLinearActivation_Type_NUM 5
 #define PyBobLearnLinearActivation_Type_TYPE PyTypeObject
 
 /***********************************************
@@ -73,10 +77,10 @@ typedef struct {
 
 typedef struct {
   PyBobLearnActivationObject parent;
-  bob::machine::LogisticActivation* base;
+  boost::shared_ptr<bob::machine::LogisticActivation> cxx;
 } PyBobLearnLogisticActivationObject;
 
-#define PyBobLearnLogisticActivation_Type_NUM 5
+#define PyBobLearnLogisticActivation_Type_NUM 6
 #define PyBobLearnLogisticActivation_Type_TYPE PyTypeObject
 
 /********************************************************
@@ -85,10 +89,10 @@ typedef struct {
 
 typedef struct {
   PyBobLearnActivationObject parent;
-  bob::machine::HyperbolicTangentActivation* base;
+  boost::shared_ptr<bob::machine::HyperbolicTangentActivation> cxx;
 } PyBobLearnHyperbolicTangentActivationObject;
 
-#define PyBobLearnHyperbolicTangentActivation_Type_NUM 6
+#define PyBobLearnHyperbolicTangentActivation_Type_NUM 7
 #define PyBobLearnHyperbolicTangentActivation_Type_TYPE PyTypeObject
 
 /******************************************************************
@@ -97,14 +101,14 @@ typedef struct {
 
 typedef struct {
   PyBobLearnActivationObject parent;
-  bob::machine::MultipliedHyperbolicTangentActivation* base;
+  boost::shared_ptr<bob::machine::MultipliedHyperbolicTangentActivation> cxx;
 } PyBobLearnMultipliedHyperbolicTangentActivationObject;
 
-#define PyBobLearnMultipliedHyperbolicTangentActivation_Type_NUM 7
+#define PyBobLearnMultipliedHyperbolicTangentActivation_Type_NUM 8
 #define PyBobLearnMultipliedHyperbolicTangentActivation_Type_TYPE PyTypeObject
 
 /* Total number of C API pointers */
-#define PyXbobLearnActivation_API_pointers 8
+#define PyXbobLearnActivation_API_pointers 9
 
 #ifdef XBOB_LEARN_ACTIVATION_MODULE
 
@@ -124,6 +128,8 @@ typedef struct {
 
   PyBobLearnActivation_Check_RET PyBobLearnActivation_Check PyBobLearnActivation_Check_PROTO;
 
+  PyBobLearnActivation_NewFromActivation_RET PyBobLearnActivation_NewFromActivation PyBobLearnActivation_NewFromActivation_PROTO;
+
   /***********************************************
    * Bindings for xbob.learn.activation.Identity *
    ***********************************************/
@@ -194,6 +200,8 @@ typedef struct {
 
 # define PyBobLearnActivation_Check (*(PyBobLearnActivation_Check_RET (*)PyBobLearnActivation_Check_PROTO) PyXbobLearnActivation_API[PyBobLearnActivation_Check_NUM])
 
+# define PyBobLearnActivation_NewFromActivation (*(PyBobLearnActivation_NewFromActivation_RET (*)PyBobLearnActivation_NewFromActivation_PROTO) PyXbobLearnActivation_API[PyBobLearnActivation_NewFromActivation_NUM])
+
   /***********************************************
    * Bindings for xbob.learn.activation.Identity *
    ***********************************************/
diff --git a/xbob/learn/activation/linear.cpp b/xbob/learn/activation/linear.cpp
index 491ebd6b06af7e571ae294878b710bbf77a4237a..bb338052e4dc75afb19e0c5b136a5487bfb9f2ce 100644
--- a/xbob/learn/activation/linear.cpp
+++ b/xbob/learn/activation/linear.cpp
@@ -33,7 +33,7 @@ static int PyBobLearnLinearActivation_init
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "|d", kwlist, &C)) return -1;
 
   try {
-    self->base = new bob::machine::LinearActivation(C);
+    self->cxx.reset(new bob::machine::LinearActivation(C));
   }
   catch (std::exception& ex) {
     PyErr_SetString(PyExc_RuntimeError, ex.what());
@@ -42,7 +42,7 @@ static int PyBobLearnLinearActivation_init
     PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_linearactivation_str);
   }
 
-  self->parent.base = self->base;
+  self->parent.cxx = self->cxx;
 
   if (PyErr_Occurred()) return -1;
 
@@ -53,9 +53,8 @@ static int PyBobLearnLinearActivation_init
 static void PyBobLearnLinearActivation_delete
 (PyBobLearnLinearActivationObject* self) {
 
-  delete self->base;
-  self->parent.base = 0;
-  self->base = 0;
+  self->parent.cxx.reset();
+  self->cxx.reset();
   self->parent.ob_type->tp_free((PyObject*)self);
 
 }
@@ -68,7 +67,7 @@ PyDoc_STRVAR(s_C_doc,
 static PyObject* PyBobLearnLinearActivation_C
 (PyBobLearnLinearActivationObject* self) {
 
-  return Py_BuildValue("d", self->base->C());
+  return Py_BuildValue("d", self->cxx->C());
 
 }
 
diff --git a/xbob/learn/activation/logistic.cpp b/xbob/learn/activation/logistic.cpp
index 34c223347c3cac89a193730a02abb70e2a9793ed..ba5af66f730fa8b90a6cace9c6beb7e0eb8c12c9 100644
--- a/xbob/learn/activation/logistic.cpp
+++ b/xbob/learn/activation/logistic.cpp
@@ -27,7 +27,7 @@ static int PyBobLearnLogisticActivation_init
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return -1;
 
   try {
-    self->base = new bob::machine::LogisticActivation();
+    self->cxx.reset(new bob::machine::LogisticActivation());
   }
   catch (std::exception& ex) {
     PyErr_SetString(PyExc_RuntimeError, ex.what());
@@ -36,7 +36,7 @@ static int PyBobLearnLogisticActivation_init
     PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_logisticactivation_str);
   }
 
-  self->parent.base = self->base;
+  self->parent.cxx = self->cxx;
 
   if (PyErr_Occurred()) return -1;
 
@@ -47,9 +47,8 @@ static int PyBobLearnLogisticActivation_init
 static void PyBobLearnLogisticActivation_delete
 (PyBobLearnLogisticActivationObject* self) {
 
-  delete self->base;
-  self->parent.base = 0;
-  self->base = 0;
+  self->parent.cxx.reset();
+  self->cxx.reset();
   self->parent.ob_type->tp_free((PyObject*)self);
 
 }
diff --git a/xbob/learn/activation/main.cpp b/xbob/learn/activation/main.cpp
index 053230940119bbf84ddb90ffaaac788a945d95e8..7e25978753261f6f166ed0fc69f6bc3606ab59f8 100644
--- a/xbob/learn/activation/main.cpp
+++ b/xbob/learn/activation/main.cpp
@@ -89,6 +89,8 @@ PyMODINIT_FUNC XBOB_EXT_ENTRY_NAME (void) {
 
   PyXbobLearnActivation_API[PyBobLearnActivation_Check_NUM] = (void *)&PyBobLearnActivation_Check;
 
+  PyXbobLearnActivation_API[PyBobLearnActivation_NewFromActivation_NUM] = (void *)&PyBobLearnActivation_NewFromActivation;
+
   /***********************************************
    * Bindings for xbob.learn.activation.Identity *
    ***********************************************/
diff --git a/xbob/learn/activation/mult_tanh.cpp b/xbob/learn/activation/mult_tanh.cpp
index 72038bb3ed12e8880c4348876f16befcd7c43053..95e4acc10bfa02a34bbb108f30f124cd682dc52f 100644
--- a/xbob/learn/activation/mult_tanh.cpp
+++ b/xbob/learn/activation/mult_tanh.cpp
@@ -38,7 +38,7 @@ static int PyBobLearnMultipliedHyperbolicTangentActivation_init
     return -1;
 
   try {
-    self->base = new bob::machine::MultipliedHyperbolicTangentActivation(C, M);
+    self->cxx.reset(new bob::machine::MultipliedHyperbolicTangentActivation(C, M));
   }
   catch (std::exception& ex) {
     PyErr_SetString(PyExc_RuntimeError, ex.what());
@@ -47,7 +47,7 @@ static int PyBobLearnMultipliedHyperbolicTangentActivation_init
     PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_multtanhactivation_str);
   }
 
-  self->parent.base = self->base;
+  self->parent.cxx = self->cxx;
 
   if (PyErr_Occurred()) return -1;
 
@@ -58,9 +58,8 @@ static int PyBobLearnMultipliedHyperbolicTangentActivation_init
 static void PyBobLearnMultipliedHyperbolicTangentActivation_delete
 (PyBobLearnMultipliedHyperbolicTangentActivationObject* self) {
 
-  delete self->base;
-  self->parent.base = 0;
-  self->base = 0;
+  self->parent.cxx.reset();
+  self->cxx.reset();
   self->parent.ob_type->tp_free((PyObject*)self);
 
 }
@@ -74,7 +73,7 @@ tangent function (read-only).\n\
 static PyObject* PyBobLearnMultipliedHyperbolicTangentActivation_C
 (PyBobLearnMultipliedHyperbolicTangentActivationObject* self) {
 
-  return Py_BuildValue("d", self->base->C());
+  return Py_BuildValue("d", self->cxx->C());
 
 }
 
@@ -88,7 +87,7 @@ tangent function (read-only).\n\
 static PyObject* PyBobLearnMultipliedHyperbolicTangentActivation_M
 (PyBobLearnMultipliedHyperbolicTangentActivationObject* self) {
 
-  return Py_BuildValue("d", self->base->M());
+  return Py_BuildValue("d", self->cxx->M());
 
 }
 
diff --git a/xbob/learn/activation/tanh.cpp b/xbob/learn/activation/tanh.cpp
index d310a7ac37a439a39f28cb76f1ecedc6a44053b0..866a713e98d4fd457adbde647b74fae9e6fd9997 100644
--- a/xbob/learn/activation/tanh.cpp
+++ b/xbob/learn/activation/tanh.cpp
@@ -29,7 +29,7 @@ static int PyBobLearnHyperbolicTangentActivation_init
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) return -1;
 
   try {
-    self->base = new bob::machine::HyperbolicTangentActivation();
+    self->cxx.reset(new bob::machine::HyperbolicTangentActivation());
   }
   catch (std::exception& ex) {
     PyErr_SetString(PyExc_RuntimeError, ex.what());
@@ -38,7 +38,7 @@ static int PyBobLearnHyperbolicTangentActivation_init
     PyErr_Format(PyExc_RuntimeError, "cannot create new object of type `%s' - unknown exception thrown", s_hyperbolictangentactivation_str);
   }
 
-  self->parent.base = self->base;
+  self->parent.cxx = self->cxx;
 
   if (PyErr_Occurred()) return -1;
 
@@ -49,9 +49,8 @@ static int PyBobLearnHyperbolicTangentActivation_init
 static void PyBobLearnHyperbolicTangentActivation_delete
 (PyBobLearnHyperbolicTangentActivationObject* self) {
 
-  delete self->base;
-  self->parent.base = 0;
-  self->base = 0;
+  self->parent.cxx.reset();
+  self->cxx.reset();
   self->parent.ob_type->tp_free((PyObject*)self);
 
 }