diff --git a/include/eigenpy/details.hpp b/include/eigenpy/details.hpp
index 58ed6ad064ebcd0e55ad55bae0dc989022d65d4d..dadfe458e2a60b91876547997ebe097e09ff2a1e 100644
--- a/include/eigenpy/details.hpp
+++ b/include/eigenpy/details.hpp
@@ -49,6 +49,20 @@ namespace boost { namespace python { namespace detail {
           std::size_t, value = sizeof(MatType));
   };
 
+  template<class MatType>
+  struct referent_size<Eigen::PlainObjectBase<MatType>&>
+  {
+      BOOST_STATIC_CONSTANT(
+          std::size_t, value = sizeof(MatType));
+  };
+
+  template<class MatType>
+  struct referent_size<Eigen::PlainObjectBase<MatType> >
+  {
+      BOOST_STATIC_CONSTANT(
+          std::size_t, value = sizeof(MatType));
+  };
+
 }}}
 
 namespace eigenpy
@@ -65,7 +79,13 @@ namespace eigenpy
   {
     if(check_registration<MatType>()) return;
     
+    // to-python
     EigenToPyConverter<MatType>::registration();
+#if EIGEN_VERSION_AT_LEAST(3,2,0)
+    EigenToPyConverter< Eigen::Ref<MatType> >::registration();
+#endif
+    
+    // from-python
     EigenFromPyConverter<MatType>::registration();
   }
 
diff --git a/include/eigenpy/eigen-from-python.hpp b/include/eigenpy/eigen-from-python.hpp
index 83beda216ff335ae42e7ab291d725d8dbf578c9c..1a55bcbaba45bdba843a86a979c41bf5f046fb3c 100644
--- a/include/eigenpy/eigen-from-python.hpp
+++ b/include/eigenpy/eigen-from-python.hpp
@@ -173,6 +173,14 @@ namespace boost { namespace python { namespace converter {
     EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(Derived const &)
   };
 
+  /// \brief Template specialization of rvalue_from_python_data
+  template<typename Derived>
+  struct rvalue_from_python_data<Eigen::PlainObjectBase<Derived> const &>
+  : rvalue_from_python_data_eigen<Derived const &>
+  {
+    EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(Derived const &)
+  };
+
   template<typename MatType, int Options, typename Stride>
   struct rvalue_from_python_data<Eigen::Ref<MatType,Options,Stride> &>
   : rvalue_from_python_storage<Eigen::Ref<MatType,Options,Stride> &>
@@ -425,6 +433,10 @@ namespace eigenpy
       typedef Eigen::EigenBase<MatType> EigenBase;
       EigenFromPy<EigenBase>::registration();
 
+      // Add conversion to Eigen::PlainObjectBase<MatType>
+      typedef Eigen::PlainObjectBase<MatType> PlainObjectBase;
+      EigenFromPy<PlainObjectBase>::registration();
+
 #if EIGEN_VERSION_AT_LEAST(3,2,0)
       // Add conversion to Eigen::Ref<MatType>
       typedef Eigen::Ref<MatType> RefType;
@@ -464,6 +476,20 @@ namespace eigenpy
        &EigenFromPy::construct,bp::type_id<Base>());
     }
   };
+    
+  template<typename MatType>
+  struct EigenFromPy< Eigen::PlainObjectBase<MatType> > : EigenFromPy<MatType>
+  {
+    typedef EigenFromPy<MatType> EigenFromPyDerived;
+    typedef Eigen::PlainObjectBase<MatType> Base;
+
+    static void registration()
+    {
+      bp::converter::registry::push_back
+      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
+       &EigenFromPy::construct,bp::type_id<Base>());
+    }
+  };
 
 #if EIGEN_VERSION_AT_LEAST(3,2,0)
 
diff --git a/include/eigenpy/eigen-to-python.hpp b/include/eigenpy/eigen-to-python.hpp
index fac253712cbee8f3ee968c6080a5240c04b9bacb..bd89fec522f79a56932f8e0fd33732284f6bb6aa 100644
--- a/include/eigenpy/eigen-to-python.hpp
+++ b/include/eigenpy/eigen-to-python.hpp
@@ -82,6 +82,36 @@ namespace eigenpy
     }
   };
 
+  template<typename MatType, int Options, typename Stride>
+  struct EigenToPy< Eigen::Ref<MatType,Options,Stride> >
+  {
+    static PyObject* convert(const Eigen::Ref<MatType,Options,Stride> & mat)
+    {
+      typedef Eigen::Ref<MatType,Options,Stride> EigenRef;
+      
+      assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
+             && "Matrix range larger than int ... should never happen." );
+      const npy_intp R = (npy_intp)mat.rows(), C = (npy_intp)mat.cols();
+      
+      PyArrayObject* pyArray;
+      // Allocate Python memory
+      if( ( ((!(C == 1) != !(R == 1)) && !MatType::IsVectorAtCompileTime) || MatType::IsVectorAtCompileTime)
+         && NumpyType::getType() == ARRAY_TYPE) // Handle array with a single dimension
+      {
+        npy_intp shape[1] = { C == 1 ? R : C };
+        pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),1,shape);
+      }
+      else
+      {
+        npy_intp shape[2] = { R,C };
+        pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),2,shape);
+      }
+      
+      // Create an instance (either np.array or np.matrix)
+      return NumpyType::make(pyArray).ptr();
+    }
+  };
+
   template<typename MatType>
   struct EigenToPyConverter
   {
diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp
index a627c8abbd66dc810d92109a30817552c6675008..9cbeb8a0415c529564bbb2452966f88b947abe32 100644
--- a/include/eigenpy/numpy-allocator.hpp
+++ b/include/eigenpy/numpy-allocator.hpp
@@ -57,7 +57,7 @@ namespace eigenpy
       }
       else
       {
-        return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape);
+        return NumpyAllocator<MatType>::allocate(mat,nd,shape);
       }
     }
   };
@@ -65,8 +65,33 @@ namespace eigenpy
 #if EIGEN_VERSION_AT_LEAST(3,2,0)
 
   template<typename MatType, int Options, typename Stride>
-  struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> > : NumpyAllocator<MatType &>
+  struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> >
   {
+    typedef Eigen::Ref<MatType,Options,Stride> RefType;
+    
+    static PyArrayObject * allocate(RefType & mat,
+                                    npy_intp nd, npy_intp * shape)
+    {
+      typedef typename RefType::Scalar Scalar;
+      enum { NPY_ARRAY_MEMORY_CONTIGUOUS = RefType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY };
+      
+      if(NumpyType::sharedMemory())
+      {
+        const int Scalar_type_code = Register::getTypeCode<Scalar>();
+        PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
+                                                                    static_cast<int>(nd),
+                                                                    shape,
+                                                                    Scalar_type_code,
+                                                                    mat.data(),
+                                                                    NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);
+        
+        return pyArray;
+      }
+      else
+      {
+        return NumpyAllocator<MatType>::allocate(mat,nd,shape);
+      }
+    }
   };
 
 #endif
@@ -88,14 +113,14 @@ namespace eigenpy
                                                                     static_cast<int>(nd),
                                                                     shape,
                                                                     Scalar_type_code,
-                                                                    const_cast<SimilarMatrixType &>(mat.derived()).data(),
+                                                                    const_cast<Scalar *>(mat.data()),
                                                                     NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
                                                                     
         return pyArray;
       }
       else
       {
-        return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape);
+        return NumpyAllocator<MatType>::allocate(mat,nd,shape);
       }
     }
   };
@@ -103,8 +128,34 @@ namespace eigenpy
 #if EIGEN_VERSION_AT_LEAST(3,2,0)
 
   template<typename MatType, int Options, typename Stride>
-  struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> > : NumpyAllocator<const MatType &>
+  struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> >
   {
+    typedef const Eigen::Ref<const MatType,Options,Stride> RefType;
+    
+    template<typename SimilarMatrixType>
+    static PyArrayObject * allocate(RefType & mat,
+                                    npy_intp nd, npy_intp * shape)
+    {
+      typedef typename SimilarMatrixType::Scalar Scalar;
+      enum { NPY_ARRAY_MEMORY_CONTIGUOUS_RO = SimilarMatrixType::IsRowMajor ? NPY_ARRAY_CARRAY_RO : NPY_ARRAY_FARRAY_RO };
+      
+      if(NumpyType::sharedMemory())
+      {
+        const int Scalar_type_code = Register::getTypeCode<Scalar>();
+        PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
+                                                                    static_cast<int>(nd),
+                                                                    shape,
+                                                                    Scalar_type_code,
+                                                                    const_cast<Scalar *>(mat.data()),
+                                                                    NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
+                                                                    
+        return pyArray;
+      }
+      else
+      {
+        return NumpyAllocator<MatType>::allocate(mat,nd,shape);
+      }
+    }
   };
 
 #endif
diff --git a/unittest/eigen_ref.cpp b/unittest/eigen_ref.cpp
index 1e58cfee4c7760169a605a79f3547b4a43369081..267f4a00666aed7082c38b1ebf334efae66f2113 100644
--- a/unittest/eigen_ref.cpp
+++ b/unittest/eigen_ref.cpp
@@ -37,6 +37,14 @@ void fill(Eigen::Ref<MatType> mat, const typename MatType::Scalar & value)
   mat.fill(value);
 }
 
+template<typename MatType>
+Eigen::Ref<MatType> asRef(const int rows, const int cols)
+{
+  static MatType mat(rows,cols);
+  std::cout << "mat:\n" << mat << std::endl;
+  return mat;
+}
+
 BOOST_PYTHON_MODULE(eigen_ref)
 {
   namespace bp = boost::python;
@@ -56,4 +64,6 @@ BOOST_PYTHON_MODULE(eigen_ref)
   bp::def("fillVec3", fill<Vector3d>);
   bp::def("fillVec", fill<VectorXd>);
   bp::def("fill", fill<MatrixXd>);
+  
+  bp::def("asRef", asRef<MatrixXd>);
 }
diff --git a/unittest/matrix.cpp b/unittest/matrix.cpp
index ce8a1c191aafb95e000b85e4eb3d111d04f70fd1..fd4ebae04b87b10d864e27bd0a3cc5e86bdb2763 100644
--- a/unittest/matrix.cpp
+++ b/unittest/matrix.cpp
@@ -81,6 +81,12 @@ MatrixDerived base(const Eigen::MatrixBase<MatrixDerived> & m)
   return m.derived();
 }
 
+template<typename MatrixDerived>
+MatrixDerived plain(const Eigen::PlainObjectBase<MatrixDerived> & m)
+{
+  return m.derived();
+}
+
 template<typename Scalar>
 Eigen::Matrix<Scalar,6,6> matrix6(const Scalar & value)
 {
@@ -123,6 +129,9 @@ BOOST_PYTHON_MODULE(matrix)
   
   bp::def("base", base<VectorXd>);
   bp::def("base", base<MatrixXd>);
+  
+  bp::def("plain", plain<VectorXd>);
+  bp::def("plain", plain<MatrixXd>);
 
   bp::def("matrix6", matrix6<double>);
 }
diff --git a/unittest/python/test_eigen_ref.py b/unittest/python/test_eigen_ref.py
index fe8cd29e386162e52b5292681d6611f228532524..76721a3f2bb6080b0e7f3a9df1a0f8965f3a33d1 100644
--- a/unittest/python/test_eigen_ref.py
+++ b/unittest/python/test_eigen_ref.py
@@ -8,6 +8,16 @@ def test(mat):
   printMatrix(mat)
   assert np.array_equal(mat,np.full(mat.shape,1.))
 
+  A_ref = asRef(mat.shape[0],mat.shape[1])
+  A_ref.fill(1.)
+  A_ref2 = asRef(mat.shape[0],mat.shape[1])
+
+  assert np.array_equal(A_ref,A_ref2)
+
+  A_ref2.fill(0)
+  assert np.array_equal(A_ref,A_ref2)
+  
+
 rows = 10
 cols = 30
 
diff --git a/unittest/python/test_matrix.py b/unittest/python/test_matrix.py
index 5734eb92af3f25b6569cff7cb50a3f37f8e676c9..1b1ea6e739147df959056af916bee23827f11da3 100644
--- a/unittest/python/test_matrix.py
+++ b/unittest/python/test_matrix.py
@@ -36,6 +36,10 @@ Mref = np.reshape(np.array(range(64),np.double),[8,8])
 Mref_from_base = eigenpy.base(Mref)
 assert( np.array_equal(Mref,Mref_from_base) );
 
+# Test plain function
+Mref_from_plain = eigenpy.plain(Mref)
+assert( np.array_equal(Mref,Mref_from_plain) );
+
 if verbose: print("===> Matrix 8x8")
 M = Mref
 assert( np.array_equal(M,eigenpy.reflex(M,verbose)) );