diff --git a/CMakeLists.txt b/CMakeLists.txt
index aff6ab2830bbb0be1552d87cf97b94f6c792f8e0..e4a2f613074f4efef79f1037b7f981302353289d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,7 @@ opt(MSVC_STATIC_RUNTIME "Enable static Visual C++ runtime" OFF)
 opt(MUMPS "Enable MUMPS sparse direct linear solver" OFF)
 opt(NATIVE_FILE_CHOOSER "Enable native file chooser in GUI" ${DEFAULT})
 opt(NETGEN "Enable Netgen 3D frontal mesh generator" ${DEFAULT})
+opt(NUMPY "Enable conversion between fullMatrix and numpy array (requires SWIG)" OFF)
 opt(OCC "Enable Open CASCADE geometrical models" ${DEFAULT})
 opt(ONELAB "Enable OneLab solver interface" ${DEFAULT})
 opt(ONELAB_METAMODEL "Enable OneLab metamodels (experimental)" ${DEFAULT})
@@ -1052,6 +1053,29 @@ if(ENABLE_ACIS)
   endif(ACIS_LIB)
 endif(ENABLE_ACIS)
 
+if(ENABLE_WRAP_PYTHON)
+  find_package(SWIG)
+  find_package(PythonLibs)
+  if(SWIG_FOUND AND PYTHONLIBS_FOUND)
+    message(STATUS "Found SWIG version " ${SWIG_VERSION})
+    string(SUBSTRING ${SWIG_VERSION} 0 1 SWIG_MAJOR_VERSION)
+    if(SWIG_MAJOR_VERSION EQUAL 1)
+      message(WARNING "Python bindings require SWIG >= 2: disabling Python")
+    else(SWIG_MAJOR_VERSION EQUAL 1)
+      set_config_option(HAVE_PYTHON "Python")
+    endif(SWIG_MAJOR_VERSION EQUAL 1)
+  endif(SWIG_FOUND AND PYTHONLIBS_FOUND)
+endif(ENABLE_WRAP_PYTHON)
+
+if(HAVE_PYTHON)
+  if(ENABLE_NUMPY)
+    find_path(NUMPY_INC "numpyconfig.h" HINTS ${PYTHON_INCLUDE_PATH} PATH_SUFFIXES /numpy)
+    if(NUMPY_INC)
+      set_config_option(HAVE_NUMPY "Numpy")
+    endif(NUMPY_INC)
+  endif(ENABLE_NUMPY)
+endif(HAVE_PYTHON)
+
 check_function_exists(vsnprintf HAVE_VSNPRINTF)
 if(NOT HAVE_VSNPRINTF AND NOT ENABLE_BUILD_IOS)
   set_config_option(HAVE_NO_VSNPRINTF "NoVsnprintf")
@@ -1576,19 +1600,9 @@ else(APPLE AND ENABLE_OS_SPECIFIC_INSTALL)
   set(CPACK_GENERATOR TGZ)
 endif(APPLE AND ENABLE_OS_SPECIFIC_INSTALL)
 
-if(ENABLE_WRAP_PYTHON)
-  find_package(SWIG)
-  find_package(PythonLibs)
-  if(SWIG_FOUND AND PYTHONLIBS_FOUND)
-    message(STATUS "Found SWIG version " ${SWIG_VERSION})
-    string(SUBSTRING ${SWIG_VERSION} 0 1 SWIG_MAJOR_VERSION)
-    if(SWIG_MAJOR_VERSION EQUAL 1)
-      message(WARNING "Python bindings require SWIG >= 2: disabling Python")
-    else(SWIG_MAJOR_VERSION EQUAL 1)
-      add_subdirectory(wrappers/gmshpy)
-    endif(SWIG_MAJOR_VERSION EQUAL 1)
-  endif(SWIG_FOUND AND PYTHONLIBS_FOUND)
-endif(ENABLE_WRAP_PYTHON)
+if (HAVE_PYTHON)
+  add_subdirectory(wrappers/gmshpy)
+endif(HAVE_PYTHON)
 
 if(ENABLE_WRAP_JAVA) 
   if(NOT HAVE_BLAS OR NOT HAVE_LAPACK) 
diff --git a/Common/GmshConfig.h.in b/Common/GmshConfig.h.in
index 1edfc746828d87a67a18c8c705c2c5a34d2c463e..cf3c81d219126d2661e1d7b1cdba36107fc7cc11 100644
--- a/Common/GmshConfig.h.in
+++ b/Common/GmshConfig.h.in
@@ -39,6 +39,7 @@
 #cmakedefine HAVE_MUMPS
 #cmakedefine HAVE_NATIVE_FILE_CHOOSER
 #cmakedefine HAVE_NETGEN
+#cmakedefine HAVE_NUMPY
 #cmakedefine HAVE_NO_INTPTR_T
 #cmakedefine HAVE_NO_SOCKLEN_T
 #cmakedefine HAVE_NO_STDINT_H
diff --git a/wrappers/gmshpy/gmshCommon.i b/wrappers/gmshpy/gmshCommon.i
index 47f02845dcf51463802bb887638c35519b99eec6..1efbdca9bd56c5f801cdbfeb8f5adec2b76a6005 100644
--- a/wrappers/gmshpy/gmshCommon.i
+++ b/wrappers/gmshpy/gmshCommon.i
@@ -5,6 +5,7 @@
 %include std_vector.i
 %include std_map.i
 %include cpointer.i 
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshGeo.i b/wrappers/gmshpy/gmshGeo.i
index a44493370a3960b88f5dd180a08b6374de714f85..da667b39972f6398a4d9cad475cac75eb6d23704 100644
--- a/wrappers/gmshpy/gmshGeo.i
+++ b/wrappers/gmshpy/gmshGeo.i
@@ -4,6 +4,7 @@
 %include std_string.i
 %include std_list.i
 %include std_vector.i
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshMesh.i b/wrappers/gmshpy/gmshMesh.i
index 38836cae212845de6e35522d230b32a3a1f9c853..c35f1392a6e538140abf93d785eef55fd0d65888 100644
--- a/wrappers/gmshpy/gmshMesh.i
+++ b/wrappers/gmshpy/gmshMesh.i
@@ -2,6 +2,7 @@
 %module gmshMesh
 %include std_string.i
 %include std_list.i
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshNumeric.i b/wrappers/gmshpy/gmshNumeric.i
index 7f564e759eae149d61fe4dbbe0f6855e09f316c7..9fca5e851bb094b87bdcf7a1660c02f97e04bca8 100644
--- a/wrappers/gmshpy/gmshNumeric.i
+++ b/wrappers/gmshpy/gmshNumeric.i
@@ -3,6 +3,7 @@
 
 %include std_string.i
 %include std_vector.i
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshPost.i b/wrappers/gmshpy/gmshPost.i
index 46ad08d5999da4c8d66617b76b21862d611a12b1..d30cc19dba658416f19e463a0fc9416965cd6aae 100644
--- a/wrappers/gmshpy/gmshPost.i
+++ b/wrappers/gmshpy/gmshPost.i
@@ -4,6 +4,7 @@
 %include std_string.i
 %include std_vector.i
 %include std_map.i
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshSolver.i b/wrappers/gmshpy/gmshSolver.i
index 20b8e644628d225d2388979aa2e8d8a58e24f125..2743ac5be8d37ec9e6fb1cf3c5e22f8f22b3a628 100644
--- a/wrappers/gmshpy/gmshSolver.i
+++ b/wrappers/gmshpy/gmshSolver.i
@@ -3,6 +3,7 @@
 %include std_string.i
 %include std_vector.i
 %include std_complex.i
+%import "gmshtypemaps.i"
 
 %{
   #include "GmshConfig.h"
diff --git a/wrappers/gmshpy/gmshtypemaps.i b/wrappers/gmshpy/gmshtypemaps.i
new file mode 100644
index 0000000000000000000000000000000000000000..fbc81f41c202c447679f919fa5d9952accde5d43
--- /dev/null
+++ b/wrappers/gmshpy/gmshtypemaps.i
@@ -0,0 +1,129 @@
+%fragment("fullMatrixConversionInit", "init") {
+  %#ifdef HAVE_NUMPY
+  import_array();
+  %#endif
+}
+
+%fragment("fullMatrixConversion", "header", fragment="fullMatrixConversionInit") {
+  %#include "fullMatrix.h"
+  %#include "GmshConfig.h"
+  %#ifdef HAVE_NUMPY
+  %#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+  %#include <numpy/arrayobject.h>
+  %#if NPY_API_VERSION < 0x00000007
+  %#define NPY_ARRAY_FARRAY NPY_FARRAY
+  %#endif
+  %#endif
+  fullMatrix<double> *pySequenceToFullMatrixDouble(PyObject *o) {
+    fullMatrix<double> *fm;
+    if (!PySequence_Check(o))
+      return NULL;
+    long int nRow = PySequence_Length(o);
+    for (int i = 0; i < PySequence_Length(o); ++i) {
+      PyObject *l = PySequence_GetItem(o, i);
+      long int nCol = PySequence_Length(l);
+      if (i == 0)
+        fm = new fullMatrix<double>(nRow, nCol);
+      else if (nCol != fm->size2()) {
+        delete fm;
+        return NULL;
+      }
+      for (int j = 0; j < nCol; ++j) {
+        PyObject *v = PySequence_GetItem(l, j);
+        if (PyNumber_Check(v)) {
+          (*fm)(i, j) = (float) PyFloat_AsDouble(v);
+        }
+        else {
+          delete fm;
+          return NULL;
+        }
+      }
+    }
+    return fm;
+  }
+
+  fullMatrix<double> *objToFullMatrixRO(PyObject *obj, bool &newMatrix, PyObject *&tmpObject)
+  {
+    fullMatrix<double> *fm = NULL;
+    SWIG_ConvertPtr(obj,(void **) &fm, SWIGTYPE_p_fullMatrixT_double_t, 1);
+    if (fm)
+      return fm;
+    %#ifdef HAVE_NUMPY
+    PyArrayObject *array = (PyArrayObject*)obj;
+    if (PyArray_Check(array) && PyArray_ISFARRAY_RO(array) && PyArray_NDIM(array) == 2) {
+      newMatrix = true;
+      return new fullMatrix<double>((double*)PyArray_DATA(array), PyArray_DIM(array, 0), PyArray_DIM(array, 1));
+    }
+    if ((tmpObject = PyArray_FROMANY(obj, NPY_DOUBLE, 2, 2, NPY_ARRAY_FARRAY))) {
+      array = (PyArrayObject*)tmpObject;
+      newMatrix = true;
+      return new fullMatrix<double>((double*)PyArray_DATA(array), PyArray_DIM(array, 0), PyArray_DIM(array, 1));
+    }
+    %#endif
+    if ((fm = pySequenceToFullMatrixDouble(obj)))
+      newMatrix = true;
+    return fm;
+  }
+
+  fullMatrix<double> *objToFullMatrixRW(PyObject *obj, bool &newMatrix)
+  {
+    fullMatrix<double> *fm = NULL;
+    SWIG_ConvertPtr(obj,(void **) &fm, SWIGTYPE_p_fullMatrixT_double_t, 1);
+    if (fm)
+      return fm;
+    %#ifdef HAVE_NUMPY
+    PyArrayObject *array = (PyArrayObject*)obj;
+    if (PyArray_Check(array) && PyArray_ISFARRAY(array) && PyArray_NDIM(array) == 2) {
+      newMatrix = true;
+      return new fullMatrix<double>((double*)PyArray_DATA(array), PyArray_DIM(array, 0), PyArray_DIM(array, 1));
+    }
+    %#endif
+    return NULL;
+  }
+}
+
+%typemap(in, fragment="fullMatrixConversion") const fullMatrix<double> &(PyObject *tmpObject = NULL, bool newMatrix = false){
+  $1 = objToFullMatrixRO($input, newMatrix, tmpObject);
+  if (!$1) {
+    PyErr_Format(PyExc_TypeError, "cannot convert argument %i to a fullMatrix<double>", $argnum);
+    SWIG_fail;
+  }
+}
+%typemap(freearg) const fullMatrix<double> &{
+  if (tmpObject$argnum) Py_DECREF(tmpObject$argnum);
+  if (newMatrix$argnum && $1) delete $1;
+}
+
+%typemap(in, fragment="fullMatrixConversion") fullMatrix<double> &(bool newMatrix = false){
+  $1 = objToFullMatrixRW($input, newMatrix);
+  if (!$1) {
+    PyErr_Format(PyExc_TypeError, "cannot convert argument %i to a writable fullMatrix<double>", $argnum);
+    SWIG_fail;
+  }
+}
+%typemap(freearg) fullMatrix<double> &{
+  if (newMatrix$argnum && $1) delete $1;
+}
+
+%typemap(in, fragment="fullMatrixConversion") const fullMatrix<double> *(PyObject *tmpObject = NULL, bool newMatrix = false){
+  $1 = objToFullMatrixRO($input, newMatrix, tmpObject);
+  if (!$1) {
+    PyErr_Format(PyExc_TypeError, "cannot convert argument %i to a fullMatrix<double>", $argnum);
+    SWIG_fail;
+  }
+}
+%typemap(freearg) const fullMatrix<double> *{
+  if (tmpObject$argnum) Py_DECREF(tmpObject$argnum);
+  if (newMatrix$argnum && $1) delete $1;
+}
+
+%typemap(in, fragment="fullMatrixConversion") fullMatrix<double> *(bool newMatrix = false){
+  $1 = objToFullMatrixRW($input, newMatrix);
+  if (!$1) {
+    PyErr_Format(PyExc_TypeError, "cannot convert argument %i to a writable fullMatrix<double>", $argnum);
+    SWIG_fail;
+  }
+}
+%typemap(freearg) fullMatrix<double> *{
+  if (newMatrix$argnum && $1) delete $1;
+}