diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 78128f3922c8e34f07266e859af69304a8ed00d9..60f070e2f9ff5bd6f315662d0e98af90fd5afe82 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -47,3 +47,4 @@ jobs:
           -DPYTHON_EXECUTABLE=%CONDA_PREFIX%\python.exe ^
           ..
         cmake --build . --config Release --target install
+        ctest --output-on-failure
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6925e0a8c9aacee8139da345c43023a9f09847b9..77d90c82455d05119b97d69ca758f508995d8d6c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -150,6 +150,7 @@ SET(${PROJECT_NAME}_SOURCES
   src/exception.cpp
   src/eigenpy.cpp
   src/numpy.cpp
+  src/numpy-type.cpp
   src/matrix-float.cpp
   src/matrix-complex-float.cpp
   src/matrix-complex-double.cpp
diff --git a/cmake b/cmake
index caad0fd63c5824c5cc352cc856b666d8842df6d1..9d6231d5743f6529bdd053b929a252ad95449162 160000
--- a/cmake
+++ b/cmake
@@ -1 +1 @@
-Subproject commit caad0fd63c5824c5cc352cc856b666d8842df6d1
+Subproject commit 9d6231d5743f6529bdd053b929a252ad95449162
diff --git a/include/eigenpy/eigen-from-python.hpp b/include/eigenpy/eigen-from-python.hpp
index f74bdab603e09a929a195a70f129609a7efa0745..83beda216ff335ae42e7ab291d725d8dbf578c9c 100644
--- a/include/eigenpy/eigen-from-python.hpp
+++ b/include/eigenpy/eigen-from-python.hpp
@@ -285,7 +285,7 @@ namespace eigenpy
   template<typename MatType>
   void* EigenFromPy<MatType>::convertible(PyArrayObject* pyArray)
   {
-    if(!PyArray_Check(pyArray))
+    if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
       return 0;
     
     if(!np_type_is_convertible_into_scalar<Scalar>(EIGENPY_GET_PY_ARRAY_TYPE(pyArray)))
@@ -476,7 +476,7 @@ namespace eigenpy
     /// \brief Determine if pyObj can be converted into a MatType object
     static void* convertible(PyArrayObject * pyArray)
     {
-      if(!PyArray_Check(pyArray))
+      if(!call_PyArray_Check(reinterpret_cast<PyObject*>(pyArray)))
         return 0;
       if(!PyArray_ISWRITEABLE(pyArray))
         return 0;
diff --git a/include/eigenpy/numpy-type.hpp b/include/eigenpy/numpy-type.hpp
index 1da922b2b378b30172f71bac452abb78ef15847c..b1705794e85afffa46edeee76f2f01b9cdd6d6d6 100644
--- a/include/eigenpy/numpy-type.hpp
+++ b/include/eigenpy/numpy-type.hpp
@@ -8,7 +8,6 @@
 #include "eigenpy/fwd.hpp"
 #include "eigenpy/scalar-conversion.hpp"
 
-#include <patchlevel.h> // For PY_MAJOR_VERSION
 #include <stdexcept>
 #include <typeinfo>
 #include <sstream>
@@ -73,121 +72,42 @@ namespace eigenpy
     ARRAY_TYPE
   };
   
-  struct NumpyType
+  struct EIGENPY_DLLEXPORT NumpyType
   {
     
-    static NumpyType & getInstance()
-    {
-      static NumpyType instance;
-      return instance;
-    }
+    static NumpyType & getInstance();
 
     operator bp::object () { return getInstance().CurrentNumpyType; }
 
-    static bp::object make(PyArrayObject* pyArray, bool copy = false)
-    { return make((PyObject*)pyArray,copy); }
+    static bp::object make(PyArrayObject* pyArray, bool copy = false);
     
-    static bp::object make(PyObject* pyObj, bool copy = false)
-    {
-      bp::object m;
-      if(isMatrix())
-        m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
-//        m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
-      else if(isArray())
-        m = bp::object(bp::handle<>(pyObj)); // nothing to do here
-
-      Py_INCREF(m.ptr());
-      return m;
-    }
+    static bp::object make(PyObject* pyObj, bool copy = false);
     
-    static void setNumpyType(bp::object & obj)
-    {
-      PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
-      if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
-        switchToNumpyMatrix();
-      else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
-        switchToNumpyArray();
-    }
+    static void setNumpyType(bp::object & obj);
     
-    static void sharedMemory(const bool value)
-    {
-      getInstance().shared_memory = value;
-    }
+    static void sharedMemory(const bool value);
     
-    static bool sharedMemory()
-    {
-      return getInstance().shared_memory;
-    }
+    static bool sharedMemory();
     
-    static void switchToNumpyArray()
-    {
-      getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
-      getInstance().getType() = ARRAY_TYPE;
-    }
+    static void switchToNumpyArray();
     
-    static void switchToNumpyMatrix()
-    {
-      getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
-      getInstance().getType() = MATRIX_TYPE;
-    }
+    static void switchToNumpyMatrix();
     
-    static NP_TYPE & getType()
-    {
-      return getInstance().np_type;
-    }
+    static NP_TYPE & getType();
     
-    static bp::object getNumpyType()
-    {
-      return getInstance().CurrentNumpyType;
-    }
+    static bp::object getNumpyType();
     
-    static const PyTypeObject * getNumpyMatrixType()
-    {
-      return getInstance().NumpyMatrixType;
-    }
+    static const PyTypeObject * getNumpyMatrixType();
     
-    static const PyTypeObject * getNumpyArrayType()
-    {
-      return getInstance().NumpyArrayType;
-    }
+    static const PyTypeObject * getNumpyArrayType();
     
-    static bool isMatrix()
-    {
-      return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
-                              getInstance().NumpyMatrixType);
-    }
+    static bool isMatrix();
     
-    static bool isArray()
-    {
-      if(getInstance().isMatrix()) return false;
-      return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
-                              getInstance().NumpyArrayType);
-    }
+    static bool isArray();
 
   protected:
     
-    NumpyType()
-    {
-      pyModule = bp::import("numpy");
-      
-#if PY_MAJOR_VERSION >= 3
-      // TODO I don't know why this Py_INCREF is necessary.
-      // Without it, the destructor of NumpyType SEGV sometimes.
-      Py_INCREF(pyModule.ptr());
-#endif
-      
-      NumpyMatrixObject = pyModule.attr("matrix");
-      NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
-      NumpyArrayObject = pyModule.attr("ndarray");
-      NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
-      //NumpyAsMatrixObject = pyModule.attr("asmatrix");
-      //NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
-      
-      CurrentNumpyType = NumpyArrayObject; // default conversion
-      np_type = ARRAY_TYPE;
-      
-      shared_memory = true;
-    }
+    NumpyType();
 
     bp::object CurrentNumpyType;
     bp::object pyModule;
diff --git a/include/eigenpy/numpy.hpp b/include/eigenpy/numpy.hpp
index 184006f93292c14aebb6d5333ac75597bda1cde3..b0de2648bdfc2953afe3e14be3eaeb68e36148b4 100644
--- a/include/eigenpy/numpy.hpp
+++ b/include/eigenpy/numpy.hpp
@@ -37,6 +37,8 @@ namespace eigenpy
 #if defined _WIN32 || defined __CYGWIN__
 namespace eigenpy
 {
+  EIGENPY_DLLEXPORT bool call_PyArray_Check(PyObject *);
+
   EIGENPY_DLLEXPORT PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type);
 
   EIGENPY_DLLEXPORT PyObject* call_PyArray_New(PyTypeObject * py_type_ptr, int nd, npy_intp * shape, int np_type, void * data_ptr, int options);
@@ -52,6 +54,7 @@ namespace eigenpy
   EIGENPY_DLLEXPORT int call_PyArray_RegisterDataType(PyArray_Descr * dtype);
 }
 #else
+  #define call_PyArray_Check(py_obj) PyArray_Check(py_obj)
   #define call_PyArray_SimpleNew PyArray_SimpleNew
   #define call_PyArray_New(py_type_ptr,nd,shape,np_type,data_ptr,options) \
     PyArray_New(py_type_ptr,nd,shape,np_type,NULL,data_ptr,0,options,NULL)
diff --git a/src/numpy-type.cpp b/src/numpy-type.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cd235f01217b628e4bc337bafc17e33fe9b35d42
--- /dev/null
+++ b/src/numpy-type.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2018-2020 INRIA
+*/
+
+#include "eigenpy/numpy-type.hpp"
+
+#include <patchlevel.h> // For PY_MAJOR_VERSION
+
+namespace eigenpy
+{
+  namespace bp = boost::python;
+  
+  NumpyType & NumpyType::getInstance()
+  {
+    static NumpyType instance;
+    return instance;
+  }
+
+  bp::object NumpyType::make(PyArrayObject* pyArray, bool copy)
+  { return make((PyObject*)pyArray,copy); }
+    
+  bp::object NumpyType::make(PyObject* pyObj, bool copy)
+  {
+    bp::object m;
+    if(isMatrix())
+      m = getInstance().NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
+//    m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
+    else if(isArray())
+      m = bp::object(bp::handle<>(pyObj)); // nothing to do here
+    
+    Py_INCREF(m.ptr());
+    return m;
+  }
+    
+  void NumpyType::setNumpyType(bp::object & obj)
+  {
+    PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
+    if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
+      switchToNumpyMatrix();
+    else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
+      switchToNumpyArray();
+  }
+    
+  void NumpyType::sharedMemory(const bool value)
+  {
+    getInstance().shared_memory = value;
+  }
+    
+  bool NumpyType::sharedMemory()
+  {
+    return getInstance().shared_memory;
+  }
+    
+  void NumpyType::switchToNumpyArray()
+  {
+    getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
+    getInstance().getType() = ARRAY_TYPE;
+  }
+    
+  void NumpyType::switchToNumpyMatrix()
+  {
+    getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
+    getInstance().getType() = MATRIX_TYPE;
+  }
+    
+  NP_TYPE & NumpyType::getType()
+  {
+    return getInstance().np_type;
+  }
+    
+  bp::object NumpyType::getNumpyType()
+  {
+    return getInstance().CurrentNumpyType;
+  }
+    
+  const PyTypeObject * NumpyType::getNumpyMatrixType()
+  {
+    return getInstance().NumpyMatrixType;
+  }
+    
+  const PyTypeObject * NumpyType::getNumpyArrayType()
+  {
+    return getInstance().NumpyArrayType;
+  }
+    
+  bool NumpyType::isMatrix()
+  {
+    return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
+                            getInstance().NumpyMatrixType);
+  }
+    
+  bool NumpyType::isArray()
+  {
+    if(getInstance().isMatrix()) return false;
+    return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
+                            getInstance().NumpyArrayType);
+  }
+
+  NumpyType::NumpyType()
+  {
+    pyModule = bp::import("numpy");
+    
+#if PY_MAJOR_VERSION >= 3
+    // TODO I don't know why this Py_INCREF is necessary.
+    // Without it, the destructor of NumpyType SEGV sometimes.
+    Py_INCREF(pyModule.ptr());
+#endif
+    
+    NumpyMatrixObject = pyModule.attr("matrix");
+    NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
+    NumpyArrayObject = pyModule.attr("ndarray");
+    NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
+    //NumpyAsMatrixObject = pyModule.attr("asmatrix");
+    //NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());
+    
+    CurrentNumpyType = NumpyArrayObject; // default conversion
+    np_type = ARRAY_TYPE;
+    
+    shared_memory = true;
+  }
+}
diff --git a/src/numpy.cpp b/src/numpy.cpp
index 8833a560f3a050fa8b201e9fcdf3e5750bff792e..10c3d7ea0557a69616b4cbf6af0869d80f645605 100644
--- a/src/numpy.cpp
+++ b/src/numpy.cpp
@@ -22,6 +22,11 @@ namespace eigenpy
 
 #if defined _WIN32 || defined __CYGWIN__
 
+  bool call_PyArray_Check(PyObject * py_obj)
+  {
+    return PyArray_Check(py_obj);
+  }
+
   PyObject* call_PyArray_SimpleNew(int nd, npy_intp * shape, int np_type)
   {
     return PyArray_SimpleNew(nd,shape,np_type);
diff --git a/unittest/matrix.cpp b/unittest/matrix.cpp
index 84a116f151a37d52e4ec1b97296ed9141232deea..b7cbc593d5703e85a2d1f70de6b7f8efa8468155 100644
--- a/unittest/matrix.cpp
+++ b/unittest/matrix.cpp
@@ -81,12 +81,22 @@ MatrixDerived base(const Eigen::MatrixBase<MatrixDerived> & m)
   return m.derived();
 }
 
+template<typename Scalar>
+Eigen::Matrix<Scalar,6,6> matrix6(const Scalar & value)
+{
+  typedef Eigen::Matrix<Scalar,6,6> ReturnType;
+  return ReturnType::Constant(value);
+}
+
 BOOST_PYTHON_MODULE(matrix)
 {
   using namespace Eigen;
   namespace bp = boost::python;
   eigenpy::enableEigenPy();
 
+  typedef Eigen::Matrix<double,6,6> Matrix6;
+  eigenpy::enableEigenPySpecific<Matrix6>();
+
   Eigen::MatrixXd (*naturalsXX)(int,int,bool) = naturals;
   Eigen::VectorXd (*naturalsX)(int,bool) = naturals;
   Eigen::Matrix3d (*naturals33)(bool) = naturals;
@@ -108,4 +118,6 @@ BOOST_PYTHON_MODULE(matrix)
   
   bp::def("base", base<VectorXd>);
   bp::def("base", base<MatrixXd>);
+
+  bp::def("matrix6", matrix6<double>);
 }
diff --git a/unittest/python/test_matrix.py b/unittest/python/test_matrix.py
index 18fce68edb6a3bbb6936bf9922aabca5f77abfc6..5734eb92af3f25b6569cff7cb50a3f37f8e676c9 100644
--- a/unittest/python/test_matrix.py
+++ b/unittest/python/test_matrix.py
@@ -126,3 +126,7 @@ assert(mat1x1[0,0] == value)
 vec1x1 = eigenpy.vector1x1(value)
 assert(vec1x1.size == 1)
 assert(vec1x1[0] == value)
+
+# test registration of matrix6
+mat6 = eigenpy.matrix6(0.)
+assert(mat6.size == 36)