diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5568d339b32d22546d718d6661e6faecc0ec09db..818699d1dcb5e91211e2089557977f0505603f9b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -103,6 +103,7 @@ SET(${PROJECT_NAME}_HEADERS
   include/eigenpy/quaternion.hpp
   include/eigenpy/stride.hpp
   include/eigenpy/ref.hpp
+  include/eigenpy/details/rvalue_from_python_data.hpp
 )
 
 INCLUDE_DIRECTORIES(${${PROJECT_NAME}_BINARY_DIR}/include)
diff --git a/cmake b/cmake
index ab4c798680d0a3ba4e84d3b7f25cc42d336eca1b..242dc450ae43ca2182987c9588c21e8aab32d61c 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit ab4c798680d0a3ba4e84d3b7f25cc42d336eca1b
+Subproject commit 242dc450ae43ca2182987c9588c21e8aab32d61c
diff --git a/include/eigenpy/details.hpp b/include/eigenpy/details.hpp
index 92df398aa6839859b3797cfb2a66d00198b3b214..397625a20e40480db950a148063fa150c0014222 100644
--- a/include/eigenpy/details.hpp
+++ b/include/eigenpy/details.hpp
@@ -6,6 +6,7 @@
 #ifndef __eigenpy_details_hpp__
 #define __eigenpy_details_hpp__
 
+#include "eigenpy/details/rvalue_from_python_data.hpp"
 #include "eigenpy/fwd.hpp"
 
 #include <patchlevel.h> // For PY_MAJOR_VERSION
@@ -18,7 +19,6 @@
 
 #define GET_PY_ARRAY_TYPE(array) PyArray_ObjectType(reinterpret_cast<PyObject *>(array), 0)
 
-
 namespace eigenpy
 {
   template <typename SCALAR>  struct NumpyEquivalentType {};
@@ -146,33 +146,75 @@ namespace eigenpy
       const int rows = (int)PyArray_DIMS(pyArray)[0];
       const int cols = (int)PyArray_DIMS(pyArray)[1];
       
-      Type * mat_ptr = new(storage) Type(rows,cols);
+      Type * mat_ptr = new (storage) Type(rows,cols);
+      
+      if(NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE(pyArray))
+      {
+        *mat_ptr = MapNumpy<MatType,Scalar>::map(pyArray); // avoid useless cast
+        return;
+      }
+      
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
+      {
         *mat_ptr = MapNumpy<MatType,int>::map(pyArray).template cast<Scalar>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
+      {
         *mat_ptr = MapNumpy<MatType,long>::map(pyArray).template cast<Scalar>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
+      {
         *mat_ptr = MapNumpy<MatType,float>::map(pyArray).template cast<Scalar>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
+      {
         *mat_ptr = MapNumpy<MatType,double>::map(pyArray).template cast<Scalar>();
+        return;
+      }
     }
     
-    static void convert(Type const & mat , PyArrayObject * pyArray)
+    /// \brief Copy mat into the Python array using Eigen::Map
+    template<typename MatrixDerived>
+    static void convert(const Eigen::MatrixBase<MatrixDerived> & mat_,
+                        PyArrayObject * pyArray)
     {
+      const MatrixDerived & mat = const_cast<const MatrixDerived &>(mat_.derived());
+      
+      if(NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE(pyArray))
+      {
+        MapNumpy<MatType,Scalar>::map(pyArray) = mat; // no cast needed
+        return;
+      }
+      
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
+      {
         MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
+      {
         MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
+      {
         MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();
+        return;
+      }
       
       if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
+      {
         MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
+        return;
+      }
     }
   };
   
@@ -186,51 +228,47 @@ namespace eigenpy
     static void allocate(PyArrayObject * pyArray, void * storage)
     {
       typename MapNumpy<MatType,Scalar>::EigenMap numpyMap = MapNumpy<MatType,Scalar>::map(pyArray);
-      new(storage) Type(numpyMap);
+      new (storage) Type(numpyMap);
     }
     
-    static void convert(Type const & mat , PyArrayObject * pyArray)
+    static void convert(Type const & mat, PyArrayObject * pyArray)
     {
-      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
-        MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();
-      
-      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
-        MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();
-      
-      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
-        MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();
-      
-      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
-        MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
+      EigenObjectAllocator<MatType>::convert(mat,pyArray);
     }
   };
 #endif
+  
   /* --- TO PYTHON -------------------------------------------------------------- */
+  
   template<typename MatType>
   struct EigenToPy
   {
-    static PyObject* convert(MatType const& mat)
+    static PyObject* convert(MatType const & mat)
     {
-      typedef typename MatType::Scalar T;
+      typedef typename MatType::Scalar Scalar;
       assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX) 
 	      && "Matrix range larger than int ... should never happen." );
       const int R  = (int)mat.rows(), C = (int)mat.cols();
 
       PyArrayObject* pyArray;
-      if(C == 1 && NumpyType::getType() == ARRAY_TYPE)
+      // Allocate Python memory
+      if(C == 1 && NumpyType::getType() == ARRAY_TYPE) // Handle array with a single dimension
       {
         npy_intp shape[1] = { R };
         pyArray = (PyArrayObject*) PyArray_SimpleNew(1, shape,
-                                                     NumpyEquivalentType<T>::type_code);
+                                                     NumpyEquivalentType<Scalar>::type_code);
       }
       else
       {
         npy_intp shape[2] = { R,C };
         pyArray = (PyArrayObject*) PyArray_SimpleNew(2, shape,
-                                                     NumpyEquivalentType<T>::type_code);
+                                                     NumpyEquivalentType<Scalar>::type_code);
       }
 
+      // Allocate memory
       EigenObjectAllocator<MatType>::convert(mat,pyArray);
+      
+      // Create an instance (either np.array or np.matrix)
       return NumpyType::getInstance().make(pyArray).ptr();
     }
   };
@@ -240,19 +278,19 @@ namespace eigenpy
   template<typename MatType>
   struct EigenFromPy
   {
-    // Determine if obj_ptr can be converted in a Eigenvec
-    static void* convertible(PyArrayObject* obj_ptr)
+    /// \brief Determine if pyObj can be converted into a MatType object
+    static void* convertible(PyArrayObject* pyObj)
     {
-      if (!PyArray_Check(obj_ptr))
+      if (!PyArray_Check(pyObj))
         return 0;
 
       if(MatType::IsVectorAtCompileTime)
       {
         // Special care of scalar matrix of dimension 1x1.
-        if(PyArray_DIMS(obj_ptr)[0] == 1 && PyArray_DIMS(obj_ptr)[1] == 1)
-          return obj_ptr;
+        if(PyArray_DIMS(pyObj)[0] == 1 && PyArray_DIMS(pyObj)[1] == 1)
+          return pyObj;
         
-        if(PyArray_DIMS(obj_ptr)[0] > 1 && PyArray_DIMS(obj_ptr)[1] > 1)
+        if(PyArray_DIMS(pyObj)[0] > 1 && PyArray_DIMS(pyObj)[1] > 1)
         {
 #ifndef NDEBUG
           std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl;
@@ -260,8 +298,8 @@ namespace eigenpy
           return 0;
         }
         
-        if(((PyArray_DIMS(obj_ptr)[0] == 1) && (MatType::ColsAtCompileTime == 1))
-           || ((PyArray_DIMS(obj_ptr)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
+        if(((PyArray_DIMS(pyObj)[0] == 1) && (MatType::ColsAtCompileTime == 1))
+           || ((PyArray_DIMS(pyObj)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
         {
 #ifndef NDEBUG
           if(MatType::ColsAtCompileTime == 1)
@@ -273,9 +311,9 @@ namespace eigenpy
         }
       }
       
-      if (PyArray_NDIM(obj_ptr) != 2)
+      if (PyArray_NDIM(pyObj) != 2)
       {
-        if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
+        if ( (PyArray_NDIM(pyObj) !=1) || (! MatType::IsVectorAtCompileTime) )
         {
 #ifndef NDEBUG
           std::cerr << "The number of dimension of the object is not correct." << std::endl;
@@ -284,10 +322,10 @@ namespace eigenpy
         }
       }
       
-      if (PyArray_NDIM(obj_ptr) == 2)
+      if (PyArray_NDIM(pyObj) == 2)
       {
-        const int R = (int)PyArray_DIMS(obj_ptr)[0];
-        const int C = (int)PyArray_DIMS(obj_ptr)[1];
+        const int R = (int)PyArray_DIMS(pyObj)[0];
+        const int C = (int)PyArray_DIMS(pyObj)[1];
         
         if( (MatType::RowsAtCompileTime!=R)
            && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
@@ -298,7 +336,7 @@ namespace eigenpy
       }
       
       // Check if the Scalar type of the obj_ptr is compatible with the Scalar type of MatType
-      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_INT)
+      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(pyObj), 0)) == NPY_INT)
       {
         if(!FromTypeToType<int,typename MatType::Scalar>::value)
         {
@@ -308,7 +346,7 @@ namespace eigenpy
           return 0;
         }
       }
-      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_LONG)
+      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(pyObj), 0)) == NPY_LONG)
       {
         if(!FromTypeToType<long,typename MatType::Scalar>::value)
         {
@@ -318,7 +356,7 @@ namespace eigenpy
           return 0;
         }
       }
-      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_FLOAT)
+      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(pyObj), 0)) == NPY_FLOAT)
       {
         if(!FromTypeToType<float,typename MatType::Scalar>::value)
         {
@@ -328,7 +366,7 @@ namespace eigenpy
           return 0;
         }
       }
-      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_DOUBLE)
+      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(pyObj), 0)) == NPY_DOUBLE)
       {
         if(!FromTypeToType<double,typename MatType::Scalar>::value)
         {
@@ -338,7 +376,7 @@ namespace eigenpy
           return 0;
         }
       }
-      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0))
+      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(pyObj), 0))
           != NumpyEquivalentType<typename MatType::Scalar>::type_code)
       {
 #ifndef NDEBUG
@@ -349,7 +387,7 @@ namespace eigenpy
       }
       
 #ifdef NPY_1_8_API_VERSION
-      if (!(PyArray_FLAGS(obj_ptr)))
+      if (!(PyArray_FLAGS(pyObj)))
 #else
         if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
 #endif
@@ -360,15 +398,13 @@ namespace eigenpy
           return 0;
         }
       
-      return obj_ptr;
+      return pyObj;
     }
  
-    // Convert obj_ptr into an Eigen::Vector
+    /// \brief Allocate memory and copy pyObj in the new storage
     static void construct(PyObject* pyObj,
                           bp::converter::rvalue_from_python_stage1_data* memory)
     {
-      using namespace Eigen;
-      
       PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
       assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));
       
@@ -379,6 +415,42 @@ namespace eigenpy
 
       memory->convertible = storage;
     }
+    
+    static void registration()
+    {
+      bp::converter::registry::push_back
+      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
+       &EigenFromPy::construct,bp::type_id<MatType>());
+    }
+  };
+  
+  template<typename MatType>
+  struct EigenFromPy< Eigen::MatrixBase<MatType> >
+  {
+    typedef EigenFromPy<MatType> EigenFromPyDerived;
+    typedef Eigen::MatrixBase<MatType> Base;
+    
+    /// \brief Determine if pyObj can be converted into a MatType object
+    static void* convertible(PyArrayObject* pyObj)
+    {
+      std::cout << "call: EigenFromPy< Eigen::MatrixBase<MatType> >::convertible" << std::endl;
+      return EigenFromPyDerived::convertible(pyObj);
+    }
+    
+    /// \brief Allocate memory and copy pyObj in the new storage
+    static void construct(PyObject* pyObj,
+                          bp::converter::rvalue_from_python_stage1_data* memory)
+    {
+      std::cout << "call: EigenFromPy< Eigen::MatrixBase<MatType> >::construct" << std::endl;
+      EigenFromPyDerived::construct(pyObj,memory);
+    }
+    
+    static void registration()
+    {
+      bp::converter::registry::push_back
+      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
+       &EigenFromPy::construct,bp::type_id<Base>());
+    }
   };
   
 #define numpy_import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } }
@@ -394,14 +466,11 @@ namespace eigenpy
   {
     static void registration()
     {
-      bp::converter::registry::push_back
-      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
-       &EigenFromPy<MatType>::construct,bp::type_id<MatType>());
-      
+      EigenFromPy<MatType>::registration();
+
       // Add also conversion to Eigen::MatrixBase<MatType>
-      bp::converter::registry::push_back
-      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
-       &EigenFromPy<MatType>::construct,bp::type_id< Eigen::MatrixBase<MatType> >());
+      typedef Eigen::MatrixBase<MatType> MatTypeBase;
+      EigenFromPy<MatTypeBase>::registration();
     }
   };
 
@@ -419,7 +488,6 @@ namespace eigenpy
   };
 #endif
   
-  
   template<typename MatType>
   void enableEigenPySpecific()
   {
diff --git a/include/eigenpy/details/rvalue_from_python_data.hpp b/include/eigenpy/details/rvalue_from_python_data.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..3cd94e979cc59f40f30d6f01131d144f07829136
--- /dev/null
+++ b/include/eigenpy/details/rvalue_from_python_data.hpp
@@ -0,0 +1,55 @@
+#ifndef __eigenpy_details_rvalue_from_python_data_hpp__
+#define __eigenpy_details_rvalue_from_python_data_hpp__
+
+#include <boost/python/converter/rvalue_from_python_data.hpp>
+#include <Eigen/Core>
+
+namespace boost
+{
+  namespace python
+  {
+    namespace converter
+    {
+  
+      /// \brief Template specialization of rvalue_from_python_data
+      template<typename Derived>
+      struct rvalue_from_python_data<Eigen::MatrixBase<Derived> const & >
+      : rvalue_from_python_storage<Eigen::MatrixBase<Derived> const & >
+      {
+        typedef Eigen::MatrixBase<Derived> const & T;
+        
+# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
+&& (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
+&& (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) \
+&& !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */
+        // This must always be a POD struct with m_data its first member.
+        BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0);
+# endif
+        
+        // The usual constructor
+        rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)
+        {
+          this->stage1 = _stage1;
+        }
+        
+        // This constructor just sets m_convertible -- used by
+        // implicitly_convertible<> to perform the final step of the
+        // conversion, where the construct() function is already known.
+        rvalue_from_python_data(void* convertible)
+        {
+          this->stage1.convertible = convertible;
+        }
+        
+        // Destroys any object constructed in the storage.
+        ~rvalue_from_python_data()
+        {
+          if (this->stage1.convertible == this->storage.bytes)
+            static_cast<Derived *>((void *)this->storage.bytes)->~Derived();
+        }
+      };
+      
+    }
+  }
+} // namespace boost::python::converter
+
+#endif // ifndef __eigenpy_details_rvalue_from_python_data_hpp__
diff --git a/include/eigenpy/eigenpy.hpp b/include/eigenpy/eigenpy.hpp
index 856ea52b4c211e9d8f5ea441525fe6e647582c33..0c5cc8f0cff0323ac67bedec90b7701a3abe1c96 100644
--- a/include/eigenpy/eigenpy.hpp
+++ b/include/eigenpy/eigenpy.hpp
@@ -9,19 +9,20 @@
 #include "eigenpy/fwd.hpp"
 #include "eigenpy/deprecated.hh"
 #include "eigenpy/eigenpy_export.h"
+
 #if EIGEN_VERSION_AT_LEAST(3,2,0)
 #include "eigenpy/ref.hpp"
 
 #define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
-  enableEigenPySpecific<TYPE>(); \
-  enableEigenPySpecific< eigenpy::Ref<TYPE> >();
+  ::eigenpy::enableEigenPySpecific<TYPE>(); \
+  ::eigenpy::enableEigenPySpecific< eigenpy::Ref<TYPE> >();
 
-#else
+#else // if EIGEN_VERSION_AT_LEAST(3,2,0)
 
 #define ENABLE_SPECIFIC_MATRIX_TYPE(TYPE) \
-  enableEigenPySpecific<TYPE>();
+  ::eigenpy::enableEigenPySpecific<TYPE>();
 
-#endif
+#endif // if EIGEN_VERSION_AT_LEAST(3,2,0)
 
 namespace eigenpy
 {
diff --git a/include/eigenpy/map.hpp b/include/eigenpy/map.hpp
index 6ee8d742bea9fdde32cd0bd47095e9ee5be50180..77677f59e60ccb84ba59a90d2e11d5d0952f56c6 100644
--- a/include/eigenpy/map.hpp
+++ b/include/eigenpy/map.hpp
@@ -55,8 +55,6 @@ namespace eigenpy
       const int stride2 = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
       Stride stride(stride2,stride1);
       
-      
-      
       if( (MatType::RowsAtCompileTime!=R)
          && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
       { throw eigenpy::Exception("The number of rows does not fit with the matrix type."); }
diff --git a/include/eigenpy/ref.hpp b/include/eigenpy/ref.hpp
index 1f05bd676e5c4d4f5ddd0b67e3465589a31dfe99..4ffff43950e4e69fd0464267de8be8a4835c281c 100644
--- a/include/eigenpy/ref.hpp
+++ b/include/eigenpy/ref.hpp
@@ -19,7 +19,8 @@ namespace eigenpy
 {
 
   template<typename PlainObjectTypeT>
-  struct Ref : Eigen::Ref<PlainObjectTypeT,EIGENPY_DEFAULT_ALIGNMENT_VALUE,typename StrideType<PlainObjectTypeT>::type>
+  struct Ref
+  : Eigen::Ref<PlainObjectTypeT,EIGENPY_DEFAULT_ALIGNMENT_VALUE,typename StrideType<PlainObjectTypeT>::type>
   {
   public:
     typedef Eigen::Ref<PlainObjectTypeT,EIGENPY_DEFAULT_ALIGNMENT_VALUE,typename eigenpy::template StrideType<PlainObjectTypeT>::type> Base;
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 187c04c3c33944c3628201434fc17ff94b3d6cb0..5d644dbdd388d86e3fc9b5759a7e352678f6ebfb 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -19,6 +19,8 @@ ENDMACRO(SYMLINK_AND_INSTALL_HEADERS HEADERS SUBPATH)
 
 # --- LIBRARY --- #
 SET(PYWRAP ${PROJECT_NAME}_pywrap) 
+SET(PYWRAP ${PYWRAP} PARENT_SCOPE)
+
 MAKE_DIRECTORY("${${PROJECT_NAME}_BINARY_DIR}/python/${PROJECT_NAME}")
 
 ADD_LIBRARY(${PYWRAP} SHARED main.cpp)
diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt
index 0b164f090cfbcfa79993414debb7de0860a01b47..13b61241fa08ac2291052ecb9f6515252d31c44a 100644
--- a/unittest/CMakeLists.txt
+++ b/unittest/CMakeLists.txt
@@ -41,5 +41,9 @@ ENDIF()
 
 ADD_PYTHON_UNIT_TEST("py-matrix" "unittest/python/test_matrix.py" "unittest")
 ADD_PYTHON_UNIT_TEST("py-geometry" "unittest/python/test_geometry.py" "unittest")
+
 ADD_PYTHON_UNIT_TEST("py-switch" "unittest/python/test_switch.py" "python/eigenpy")
+SET_TESTS_PROPERTIES("py-switch" PROPERTIES DEPENDS ${PYWRAP})
+
 ADD_PYTHON_UNIT_TEST("py-dimensions" "unittest/python/test_dimensions.py" "python/eigenpy")
+SET_TESTS_PROPERTIES("py-dimensions" PROPERTIES DEPENDS ${PYWRAP})