diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8497bbb5130574028ae249241d43e9eed06f0ebe..d65f9d58d61537465e07df578644411cc9f12502 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -113,8 +113,9 @@ SET(${PROJECT_NAME}_HEADERS
   include/eigenpy/geometry.hpp
   include/eigenpy/geometry-conversion.hpp
   include/eigenpy/memory.hpp
-  include/eigenpy/numpy-type.hpp
   include/eigenpy/numpy.hpp
+  include/eigenpy/numpy-allocator.hpp
+  include/eigenpy/numpy-type.hpp
   include/eigenpy/registration.hpp
   include/eigenpy/angle-axis.hpp
   include/eigenpy/quaternion.hpp
diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..b44b1c21fb1c6d80410e8fe85fe421aa70b5307e
--- /dev/null
+++ b/include/eigenpy/numpy-allocator.hpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2020 INRIA
+ */
+
+#ifndef __eigenpy_numpy_allocator_hpp__
+#define __eigenpy_numpy_allocator_hpp__
+
+#include "eigenpy/fwd.hpp"
+#include "eigenpy/numpy-type.hpp"
+#include "eigenpy/eigen-allocator.hpp"
+
+namespace eigenpy
+{
+  template<typename MatType>
+  struct NumpyAllocator
+  {
+    template<typename SimilarMatrixType>
+    static PyArrayObject * allocate(const Eigen::MatrixBase<SimilarMatrixType> & mat,
+                                    npy_intp nd, npy_intp * shape)
+    {
+      typedef typename SimilarMatrixType::Scalar Scalar;
+      
+      PyArrayObject * pyArray = (PyArrayObject*) PyArray_SimpleNew(nd, shape,
+                                                                   NumpyEquivalentType<Scalar>::type_code);
+      
+      // Copy data
+      EigenAllocator<SimilarMatrixType>::copy(mat,pyArray);
+      
+      return pyArray;
+    }
+  };
+
+  template<typename MatType>
+  struct NumpyAllocator<MatType &>
+  {
+    template<typename SimilarMatrixType>
+    static PyArrayObject * allocate(Eigen::PlainObjectBase<SimilarMatrixType> & mat,
+                                    npy_intp nd, npy_intp * shape)
+    {
+      typedef typename SimilarMatrixType::Scalar Scalar;
+      enum { NPY_ARRAY_MEMORY_CONTIGUOUS = SimilarMatrixType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY };
+      
+      PyArrayObject * pyArray = (PyArrayObject*) PyArray_New(&PyArray_Type, nd, shape,
+                                                             NumpyEquivalentType<Scalar>::type_code, NULL,
+                                                             mat.data(), 0,
+                                                             NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED,
+                                                             NULL);
+      
+      
+      return pyArray;
+    }
+  };
+
+  template<typename MatType>
+  struct NumpyAllocator<const MatType &>
+  {
+    template<typename SimilarMatrixType>
+    static PyArrayObject * allocate(const Eigen::PlainObjectBase<SimilarMatrixType> & 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 };
+      
+      PyArrayObject * pyArray = (PyArrayObject*) PyArray_New(&PyArray_Type, nd, shape,
+                                                             NumpyEquivalentType<Scalar>::type_code, NULL,
+                                                             mat.data(), 0,
+                                                             NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED,
+                                                             NULL);
+      
+      
+      return pyArray;
+    }
+  };
+}
+
+#endif // ifndef __eigenpy_numpy_allocator_hpp__