From 7da78adb7fe867db38583b89633359e997f92740 Mon Sep 17 00:00:00 2001
From: Jonathan Lambrechts <jonathan.lambrechts@uclouvain.be>
Date: Fri, 24 Nov 2017 23:39:44 +0100
Subject: [PATCH] script to extract all functions from gmsh.h, namespaces

---
 Common/gmsh.cpp |   6 +-
 Common/gmsh.h   |   8 +-
 api/GenApi.py   | 292 +++++++++++++++++++++--------------
 api/Makefile    |   1 +
 api/extract.py  |  83 ++++++++++
 api/gen.py      | 403 +++++++++++++++++-------------------------------
 api/main.c      |  40 ++---
 api/test.py     |  61 ++++----
 8 files changed, 464 insertions(+), 430 deletions(-)
 create mode 100644 api/extract.py

diff --git a/Common/gmsh.cpp b/Common/gmsh.cpp
index bffea8b6ab..2aa6a29a9e 100644
--- a/Common/gmsh.cpp
+++ b/Common/gmsh.cpp
@@ -2095,9 +2095,9 @@ void gmsh::view::probe(const int tag, const double x, const double y,
                        const double z, std::vector<double> &value,
                        const int step, const int numComp,
                        const bool gradient, const double tolerance,
-                       const std::vector<double> xElemCoord,
-                       const std::vector<double> yElemCoord,
-                       const std::vector<double> zElemCoord)
+                       const std::vector<double> &xElemCoord,
+                       const std::vector<double> &yElemCoord,
+                       const std::vector<double> &zElemCoord)
 {
   if(!_isInitialized()){ throw -1; }
 #if defined(HAVE_POST)
diff --git a/Common/gmsh.h b/Common/gmsh.h
index 594ecb6bd3..8e5b1f4f4f 100644
--- a/Common/gmsh.h
+++ b/Common/gmsh.h
@@ -692,7 +692,7 @@ namespace gmsh { // Top-level functions
                                const double z, const double dx,
                                const double dy, const double dz,
                                const double r, const int tag = -1,
-                               double angle = 2*M_PI);
+                               const double angle = 2*M_PI);
       GMSH_API int addCone(const double x, const double y, const double z,
                            const double dx, const double dy, const double dz,
                            const double r1, const double r2,
@@ -849,11 +849,11 @@ namespace gmsh { // Top-level functions
                         const int step = -1, const int numComp = -1,
                         const bool gradient = false,
                         const double tolerance = 0.,
-                        const std::vector<double> xElemCoord
+                        const std::vector<double> &xElemCoord
                         = std::vector<double>(),
-                        const std::vector<double> yElemCoord
+                        const std::vector<double> &yElemCoord
                         = std::vector<double>(),
-                        const std::vector<double> zElemCoord
+                        const std::vector<double> &zElemCoord
                         = std::vector<double>());
 
     // Writes the view to a file. The export format is determined by the file
diff --git a/api/GenApi.py b/api/GenApi.py
index 72b623fe1f..d22cfb278a 100644
--- a/api/GenApi.py
+++ b/api/GenApi.py
@@ -1,3 +1,4 @@
+import os 
 class arg:
 
     def __init__(self,name,value,type_cpp,type_c,out):
@@ -9,8 +10,7 @@ class arg:
         self.cpp_value = (" = "+value) if value else ""
 
         n = self.type_cpp 
-        if n[-1] != "&":
-            n += " "
+        n += " "
         n += self.name
         n += self.cpp_value
         self.cpp = n
@@ -37,7 +37,7 @@ class oint(arg):
         self.c_arg = "*"+name
 
 def istring(name,value=None):
-    value = "\""+value+"\"" if value is not None else None
+    #value = "\""+value+"\"" if value is not None else None
     a = arg(name,value,"const std::string&","const char*",False)
     a.python_arg = "c_char_p("+name+".encode())"
     return a
@@ -46,7 +46,7 @@ def ostring(name,value=None):
     a = arg(name,value,"std::string &","char**",True)
     a.c_arg = "api_"+name+"_"
     a.c_pre = "  std::string "+a.c_arg +";\n"
-    a.c_post = "  *"+name+" = strdup("+a.c_arg+".c_str());\n"
+    a.c_post = "  *"+name+" = _strdup("+a.c_arg+".c_str());\n"
     name_ = "api_"+name+"_"
     a.python_pre = name_+" = c_char_p()"
     a.python_arg = "byref("+name_+")"
@@ -68,20 +68,33 @@ def odouble(name,value=None):
     return a
 
 def ovectorpair(name,value=None):
-    a = arg(name,value,"vector_pair &","int**",True)
+    a = arg(name,value,"gmsh::vector_pair &","int**",True)
     name_ = "api_"+name+"_"
     name_n = name_ + "n_"
     a.c_arg = name_
-    a.c_pre = "  vector_pair "+name_ +";\n"
-    a.c_post = "  pairvector2intptr("+name_+"," + name + ","+name_n+");\n"
-    a.c = "int** "+name+",size_t* "+name_n
+    a.c_pre = "  gmsh::vector_pair "+name_ +";\n"
+    a.c_post = "  pairvector2intptr("+name_+"," + name + ","+name+"_n);\n"
+    a.c = "int** "+name+",size_t* "+name+"_n"
     a.python_pre = name_+", "+name_n+" = POINTER(c_int)(), c_size_t()"
     a.python_arg = "byref("+name_+"),byref("+name_n+")"
     a.python_return = "_ovectorpair("+name_+","+name_n+".value)"
     return a
 
+def ovectorstring(name,value=None):
+    a = arg(name,value,"std::vector<std::string> &","char**",True)
+    name_ = "api_"+name+"_"
+    name_n = name_ + "n_"
+    a.c_arg = name_
+    a.c_pre = "  std::vector<std::string> "+name_ +";\n"
+    a.c_post = "  stringvector2charpp("+name_+"," + name + ","+name+"_n);\n"
+    a.c = "char*** "+name+",size_t* "+name+"_n"
+    a.python_pre = name_+", "+name_n+" = POINTER(c_char_p)(), c_size_t()"
+    a.python_arg = "byref("+name_+"),byref("+name_n+")"
+    a.python_return = "_ovectorstring("+name_+","+name_n+".value)"
+    return a
+
 def ivectorpair(name,value=None):
-    a = arg(name,value,"const vector_pair &","const int*",False)
+    a = arg(name,value,"const gmsh::vector_pair &","const int*",False)
     a.c_arg = "intptr2pairvector("+name+","+name+"_n)"
     a.c = "int* "+name+",size_t "+name+"_n"
     a.python_pre = "api_"+name+"_, api"+name+"_n_ = _ivectorpair("+name+")"
@@ -114,8 +127,8 @@ def ovectorint(name,value=None):
     name_n = name_ + "n_"
     a.c_arg = name_
     a.c_pre = "  std::vector<int> "+name_ +";\n"
-    a.c_post = "  vector2ptr("+name_+"," + name + ","+name_n+");\n"
-    a.c = "int** "+name+",size_t* "+name_n
+    a.c_post = "  vector2ptr("+name_+"," + name + ","+name+"_n);\n"
+    a.c = "int** "+name+",size_t* "+name+"_n"
     a.python_pre = name_+", "+name_n+" = POINTER(c_int)(), c_size_t()"
     a.python_arg = "byref("+name_+"),byref("+name_n+")"
     a.python_return = "_ovectorint("+name_+","+name_n+".value)"
@@ -135,7 +148,7 @@ def ovectordouble(name,value=None):
     name_n = name_ + "n_"
     a.c_arg = name_
     a.c_pre = "  std::vector<double> "+a.c_arg +";\n"
-    a.c_post = "  vector2ptr("+name_+"," + name + ","+name_n+";\n"
+    a.c_post = "  vector2ptr("+name_+"," + name + ","+name+"_n);\n"
     a.c  = "double** "+name+",size_t* "+name+"_n"
     a.python_pre = name_+", "+name_n+" = POINTER(c_double)(), c_size_t()"
     a.python_arg = "byref("+name_+"),byref("+name_n+")"
@@ -149,22 +162,22 @@ def ovectorvectorint(name,value=None):
     name_nn = name_ + "nn_"
     a.c_arg = name_
     a.c_pre = "  std::vector<std::vector<int> > "+a.c_arg +";\n"
-    a.c_post = "  vectorvector2ptrptr("+name_+"," + name + ","+name_n+","+name_nn+");\n"
-    a.c  = "int*** "+name+",size_t** "+name_n+",size_t *"+name_nn
+    a.c_post = "  vectorvector2ptrptr("+name_+"," + name + ","+name+"_n,"+name+"_nn);\n"
+    a.c  = "int*** "+name+",size_t** "+name+"_n,size_t *"+name+"_nn"
     a.python_pre = name_+", "+name_n+", "+name_nn +" = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()"
     a.python_arg = "byref("+name_+"),byref("+name_n+"),byref("+name_nn+")"
     a.python_return = "_ovectorvectorint("+name_+","+name_n+","+name_nn+")"
     return a
 
 def ovectorvectorpair(name,value=None):
-    a = arg(name,value,"std::vector<vector_pair> &","int**",True)
+    a = arg(name,value,"std::vector<gmsh::vector_pair> &","int**",True)
     name_ = "api_"+name+"_"
     name_n = name_ + "n_"
     name_nn = name_ + "nn_"
     a.c_arg = name_
-    a.c_pre = "  std::vector<vector_pair >"+name_ +";\n"
-    a.c_post = "  pairvectorvector2intptrptr("+name_+"," + name + ","+name_n+","+name_nn+";\n"
-    a.c  = "int*** "+name+",size_t** "+name_n+",size_t *"+name_nn
+    a.c_pre = "  std::vector<gmsh::vector_pair >"+name_ +";\n"
+    a.c_post = "  pairvectorvector2intptrptr("+name_+"," + name + ","+name+"_n,"+name+"_nn);\n"
+    a.c  = "int*** "+name+",size_t** "+name+"_n,size_t *"+name+"_nn"
     a.python_pre = name_+", "+name_n+", "+name_nn +" = POINTER(POINTER(c_int))(), POINTER(c_size_t)(), c_size_t()"
     a.python_arg = "byref("+name_+"),byref("+name_n+"),byref("+name_nn+")"
     a.python_return = "_ovectorvectorpair("+name_+","+name_n+","+name_nn+")"
@@ -175,10 +188,17 @@ class Module:
     def __init__(self,name):
         self.name = name
         self.fs = []
+        self.submodules = []
 
     def add(self,rtype,name,*args):
         self.fs.append((rtype,name,args))
 
+    def add_module(self, name) :
+        module = Module(name)
+        self.submodules.append(module)
+        return module
+
+
 cpp_header="""// Gmsh - Copyright (C) 1997-2017 C. Geuzaine,J.-F. Remacle
 //
 // See the LICENSE.txt file for license information. Please report all
@@ -212,9 +232,11 @@ cpp_header="""// Gmsh - Copyright (C) 1997-2017 C. Geuzaine,J.-F. Remacle
 #define GMSH_API
 #endif
 
-typedef std::vector<std::pair<int,int> > vector_pair;
 
-GMSH_API void gmshInitialize(int argc,char **argv);
+namespace gmsh {
+  GMSH_API void initialize(int argc,char **argv);
+  typedef std::vector<std::pair<int,int> > vector_pair;
+}
 """
 
 cpp_footer=""" 
@@ -254,8 +276,8 @@ c_header="""// Gmsh - Copyright (C) 1997-2017 C. Geuzaine,J.-F. Remacle
 
 #include <stdlib.h>
 
-GMSH_API void gmshcInitialize(char argc,char **argv);
-GMSH_API void gmshcFree_(void *p);
+GMSH_API void gmshInitialize(char argc,char **argv);
+GMSH_API void gmshFree_(void *p);
 """
 
 c_footer="""
@@ -264,7 +286,7 @@ c_footer="""
 #endif
 """
 
-c_header="""// Gmsh - Copyright (C) 1997-2017 C. Geuzaine,J.-F. Remacle
+c_cpp_header="""// Gmsh - Copyright (C) 1997-2017 C. Geuzaine,J.-F. Remacle
 //
 // See the LICENSE.txt file for license information. Please report all
 // bugs and problems to the public mailing list <gmsh@onelab.info>.
@@ -275,6 +297,13 @@ extern \"C\" {
 #include "gmsh.h"
 #include <cstring>
 
+char * _strdup(const char *i) {
+  size_t len = strlen(i);
+  char *o = (char*)malloc(sizeof(char)*(len+1));
+  memcpy(o,i,len+1);
+  return o;
+}
+
 template<typename t>
 std::vector<t> ptr2vector(const t *p,size_t size) {
   return std::vector<t>(p,p+size);
@@ -289,7 +318,7 @@ void vector2ptr(const std::vector<t>&v,t **p,size_t *size) {
   *size = v.size();
 }
 
-void pairvector2intptr(const vector_pair &v,int **p,size_t *size) {
+void pairvector2intptr(const gmsh::vector_pair &v,int **p,size_t *size) {
   *p = (int*)malloc(sizeof(int)*(v.size()*2));
   for (size_t i = 0; i < v.size(); ++i){
     (*p)[i*2+0] = v[i].first;
@@ -298,8 +327,16 @@ void pairvector2intptr(const vector_pair &v,int **p,size_t *size) {
   *size = v.size()*2;
 }
 
-vector_pair intptr2pairvector(const int *p,size_t size){
-  vector_pair v(size/2);
+void stringvector2charpp(const std::vector<std::string> &v,char ***p,size_t *size) {
+  *p = (char**)malloc(sizeof(char*)*(v.size()*2));
+  for (size_t i = 0; i < v.size(); ++i){
+    (*p)[i] = _strdup(v[i].c_str());
+  }
+  *size = v.size();
+}
+
+gmsh::vector_pair intptr2pairvector(const int *p,size_t size){
+  gmsh::vector_pair v(size/2);
   for (size_t i = 0; i < size/2; ++i) {
     v[i].first = p[i*2+0];
     v[i].second = p[i*2+1];
@@ -316,18 +353,18 @@ void vectorvector2ptrptr(const std::vector<std::vector<t> > &v,t ***p,size_t **s
   *sizeSize = v.size();
 }
 
-int** pairvectorvector2intptrptr(const std::vector<vector_pair > &v,int ***p,size_t **size,size_t *sizeSize) {
+int** pairvectorvector2intptrptr(const std::vector<gmsh::vector_pair > &v,int ***p,size_t **size,size_t *sizeSize) {
   *p = (int**)malloc(sizeof(int*)*v.size());
   for (size_t i = 0; i < v.size(); ++i)
     pairvector2intptr(v[i],p[i],size[i]);
   *sizeSize = v.size();
 }
 
-void gmshcInitialize(char argc,char **argv){
-  gmshInitialize(argc,argv);
+void gmshInitialize(char argc,char **argv){
+  gmsh::initialize(argc,argv);
 }
 
-void gmshcFree_(void *p) {
+void gmshFree_(void *p) {
   if(p) free(p);
 }
 """
@@ -344,58 +381,58 @@ try :
     import numpy
     use_numpy = True
     try : 
-        from weakref import finalize
+        import weakref
     except :
-        from backports.weakref import finalize
+        from backports import weakref
 except :
     pass
 
-def Initialize() :
-    lib.gmshcInitialize(c_int(0),c_voidp(None))
+def initialize() :
+    lib.gmshInitialize(c_int(0),c_voidp(None))
 
 def _ostring(s) :
     sp = s.value.decode("utf-8")
-    lib.gmshcFree_(s)
+    lib.gmshFree_(s)
     return sp
 
 def _ovectorpair(ptr,size):
     if use_numpy :
         v = numpy.ctypeslib.as_array(ptr, (size//2,2))
-        finalize(v, lib.gmshcFree_, ptr)
+        weakref.finalize(v, lib.gmshFree_, ptr)
     else :
         v = list((ptr[i*2],ptr[i*2+1]) for i in range(size//2))
-        lib.gmshcFree_(ptr)
+        lib.gmshFree_(ptr)
     return v
 
 def _ovectorint(ptr,size):
     if use_numpy :
         v = numpy.ctypeslib.as_array(ptr, (size,))
-        finalize(v, lib.gmshcFree_, ptr)
+        weakref.finalize(v, lib.gmshFree_, ptr)
     else :
         v = list(ptr[i] for i in range(size))
-        lib.gmshcFree_(ptr)
+        lib.gmshFree_(ptr)
     return v
 
 def _ovectordouble(ptr,size):
     if use_numpy :
         v = numpy.ctypeslib.as_array(ptr, (size,))
-        finalize(v, lib.gmshcFree_, ptr)
+        weakref.finalize(v, lib.gmshFree_, ptr)
     else :
         v = list(ptr[i] for i in range(size))
-        lib.gmshcFree_(ptr)
+        lib.gmshFree_(ptr)
     return v
 
 
 def _ovectorvectorint(ptr,size,n):
     v = [_ovectorint(pointer(ptr[i].contents),size[i]) for i in range(n.value)]
-    lib.gmshcFree_(size)
-    lib.gmshcFree_(ptr)
+    lib.gmshFree_(size)
+    lib.gmshFree_(ptr)
     return v
 
 def _ovectorvectorpair(ptr,size,n):
     v = [_ovectorpair(pointer(ptr[i].contents),size[i]) for i in range(n.value)]
-    lib.gmshcFree_(size)
-    lib.gmshcFree_(ptr)
+    lib.gmshFree_(size)
+    lib.gmshFree_(ptr)
     return v
 
 def _ivectorint(o):
@@ -429,81 +466,106 @@ class API:
         self.modules.append(module)
         return module
 
-    def write_cpp(self,filename):
-        with open(filename+".h","w") as f:
+    def write_cpp(self):
+        def write_module(module,indent) :
+            f.write(indent+"namespace "+module.name +" {\n")
+            indent += "  "
+            for rtype,name,args in module.fs:
+                rt = rtype.rtype_cpp if rtype else "void"
+                f.write(indent+"GMSH_API " + rt + " " + name + "("+",".join(
+                    list((a.cpp for a in args)))+");\n")
+            for m in module.submodules :
+                write_module(m, indent)
+            f.write(indent[:-2]+"} // namespace "+ module.name+"\n")
+        with open("gmsh.h","w") as f:
             f.write(cpp_header)
-            for module in self.modules:
-                f.write("\n")
-                f.write("// gmsh"+module.name+"\n")
-                for rtype,name,args in module.fs:
-                    rt = rtype.rtype_cpp if rtype else "void"
-                    f.write("GMSH_API " + rt + " gmsh" + module.name+name+"("+",".join(
-                        list((a.cpp for a in args)))+");\n")
+            for m in self.modules:
+                write_module(m,"")
             f.write(cpp_footer)
 
-    def write_c(self,filename):
-        with open(filename+".h","w") as f:
-            f.write(c_header)
-            for module in self.modules:
-                f.write("\n")
-                f.write("/* gmsh"+module.name+" */\n")
-                for rtype,name,args in module.fs:
-                    f.write("GMSH_API "+(rtype.rtype_c if rtype else "void"))
-                    f.write(" gmshc" + module.name+name+"("
-                            +",".join(list((a.c for a in args+(oint("ierr"),))))
-                            + ");\n")
-            f.write(c_footer)
-
-        with open(filename+".cc","w") as f:
-            f.write(c_header)
-            for module in self.modules:
-                f.write("\n")
-                f.write("/* gmsh"+module.name+" */\n")
-                for rtype,name,args in module.fs:
-                    f.write(rtype.rtype_c if rtype else "void")
-                    f.write(" gmshc" + module.name+name+"("
-                        +",".join(list((a.c for a in args+(oint("ierr"),))))+"){\n")
-                    if rtype:
-                        f.write("  "+ rtype.rtype_c + " result_api_;\n")
-                    f.write("  if(ierr) *ierr = 0;\n");
-                    f.write("  try {\n");
-                    f.write("".join((a.c_pre for a in args)))
-                    f.write("  ")
-                    if rtype:
-                        f.write("result_api_ = ")
-                    f.write("gmsh" + module.name+name+"("+",".join(
-                        list((a.c_arg for a in args)))+
-                        ");\n")
-                    f.write("".join((a.c_post for a in args)))
-                    f.write("  } catch(int api_ierr_) {if (ierr) *ierr = api_ierr_;}\n");
-                    if rtype :
-                        f.write("  return result_api_;\n");
-                    f.write("}\n\n")
+    def write_c(self):
+        def c_fun_name(module, f) :
+            n = "gmshc"
+            if module :
+                n += module[0].upper() + module[1:]
+            return n + f[0].upper() + f[1:]
+        def write_module(module,c_namespace,cpp_namespace) :
+            cpp_namespace += module.name+"::"
+            if c_namespace :
+                c_namespace += module.name[0].upper()+module.name[1:]
+            else :
+                c_namespace = module.name
+            for rtype,name,args in module.fs:
+                fname = c_namespace + name[0].upper()+name[1:]
+                f.write("GMSH_API "+(rtype.rtype_c if rtype else "void"))
+                f.write(" "+fname+"("
+                        +",".join(list((a.c for a in args+(oint("ierr"),))))
+                        + ");\n")
+                fc.write(rtype.rtype_c if rtype else "void")
+                fc.write(" "+fname+"("
+                    +",".join(list((a.c for a in args+(oint("ierr"),))))+"){\n")
+                if rtype:
+                    fc.write("  "+ rtype.rtype_c + " result_api_;\n")
+                fc.write("  if(ierr) *ierr = 0;\n");
+                fc.write("  try {\n");
+                fc.write("".join((a.c_pre for a in args)))
+                fc.write("  ")
+                if rtype:
+                    fc.write("result_api_ = ")
+                fc.write(cpp_namespace+name+"("+",".join(
+                    list((a.c_arg for a in args)))+
+                    ");\n")
+                fc.write("".join((a.c_post for a in args)))
+                fc.write("  } catch(int api_ierr_) {if (ierr) *ierr = api_ierr_;}\n");
+                if rtype :
+                    fc.write("  return result_api_;\n");
+                fc.write("}\n\n")
+            for m in module.submodules :
+                write_module(m, c_namespace,cpp_namespace)
+
+        with open("gmshc.h","w") as f :
+            with open("gmshc.cc","w") as fc :
+                f.write(c_header)
+                fc.write(c_cpp_header)
+                for module in self.modules:
+                    write_module(module,"","")
+                f.write(c_footer)
 
     def write_python(self) :
+        def write_function(f,rtype, name, args, modulepath,indent):
+            iargs = list(a for a in args if not a.out)
+            oargs = list(a for a in args if a.out)
+            f.write("\n"+indent+"def "+name+"("
+                    +",".join((a.name for a in iargs))
+                    +"):\n")
+            for a in args :
+                if a.python_pre : f.write(indent+"    "+a.python_pre+"\n")
+            f.write(indent+"    ierr = c_int()\n")
+            f.write(indent+"    api__result__ = " if rtype is oint else ("    "+indent))
+            c_name = modulepath + name[0].upper()+name[1:]
+            f.write("lib."+c_name+"(\n        "+indent
+                    +(",\n"+indent+"        ").join(tuple((a.python_arg for a in args))+("byref(ierr)",))
+                    +")\n")
+            f.write(indent+"    if ierr.value != 0 :\n")
+            f.write(indent+"        raise ValueError(\""+c_name+" returned non-zero error code : \"+ str(ierr.value))\n")
+            r = (["api__result__"]) if rtype else []
+            r += list((o.python_return for o in oargs))
+            if len(r) != 0 :
+                if len(r) == 1 :
+                    f.write(indent+"    return "+r[0]+"\n")
+                else :
+                    f.write(indent+"    return (\n        "+",\n        ".join(r)+")\n")
+        def write_module(f,m,modulepath,indent) :
+            if modulepath :
+                modulepath += m.name[0].upper()+m.name[1:]
+            else :
+                modulepath = m.name
+            for fun in m.fs :
+                write_function(f,*fun,modulepath,indent)
+            for module in m.submodules :
+                f.write("\n\n"+indent + "class " + module.name + ":\n")
+                write_module(f,module,modulepath,indent+"    ")
         with open("gmsh.py","w") as f :
             f.write(python_header)
             for module in self.modules:
-                f.write("\n## gmsh"+module.name + " ##\n")
-                for (rtype,name,args) in module.fs:
-                    iargs = list(a for a in args if not a.out)
-                    oargs = list(a for a in args if a.out)
-                    f.write("\ndef "+module.name+name+"("
-                            +",".join((a.name for a in iargs))
-                            +"):\n")
-                    for a in args :
-                        if a.python_pre : f.write("    "+a.python_pre+"\n")
-                    f.write("    ierr = c_int()\n")
-                    f.write("    api__result__ = " if rtype is oint else "    ")
-                    f.write("lib.gmshc"+module.name+name+"(\n        "
-                            +",\n        ".join(tuple((a.python_arg for a in args))+("byref(ierr)",))
-                            +")\n")
-                    f.write("    if ierr.value != 0 :\n")
-                    f.write("        raise ValueError(\"gmsh."+module.name+name+" returned non-zero error code : \"+ str(ierr.value))\n")
-                    r = (["api__result__"]) if rtype else []
-                    r += list((o.python_return for o in oargs))
-                    if len(r) != 0 :
-                        if len(r) == 1 :
-                            f.write("    return "+r[0]+"\n")
-                        else :
-                            f.write("    return (\n        "+",\n        ".join(r)+")\n")
+                write_module(f,module,"","")
diff --git a/api/Makefile b/api/Makefile
index b99dda85db..2d0df2c5a1 100644
--- a/api/Makefile
+++ b/api/Makefile
@@ -1,4 +1,5 @@
 all :
+	python extract.py
 	python gen.py
 	g++  gmshc.cc -shared -fPIC -L. -L../build -Wl,-rpath=../build -lstdc++ -lgmsh -o libgmshc.so
 	gcc main.c -L. -Wl,-rpath=. -L../build -Wl,-rpath=../build  -lgmshc -lgmsh -lstdc++ -o main
diff --git a/api/extract.py b/api/extract.py
new file mode 100644
index 0000000000..03fe805658
--- /dev/null
+++ b/api/extract.py
@@ -0,0 +1,83 @@
+tmap = {
+        'int':'iint',
+        'char**':'icharpp',
+        'constbool':'ibool',
+        'constdouble':'idouble',
+        'constint':'iint',
+        'conststd::string&':'istring',
+        'conststd::vector<double>&':'ivectordouble',
+        'conststd::vector<int>&':'ivectorint',
+        'conststd::vector<std::vector<double>>&':'ivectorvectordouble',
+        'conststd::vector<std::vector<int>>&':'ivectorvectorint',
+        'constvector_pair&':'ivectorpair',
+        'double&': 'odouble',
+        'int&':'oint',
+        'std::string&':'ostring',
+        'std::vector<double>&':'ovectordouble',
+        'std::vector<int>&':'ovectorint',
+        'std::vector<std::string>&':'ovectorstring',
+        'std::vector<std::vector<int>>&':'ovectorvectorint',
+        'std::vector<vector_pair>&':'ovectorvectorpair',
+        'vector_pair&':'ovectorpair'
+}
+def parse_arg(a) :
+    value = None
+    eq = a.find("=")
+    if eq != -1 :
+        value = a[eq+1:].strip()
+        a = a[:eq].strip()
+    p = max(a.rfind(" "), a.rfind("*"), a.rfind("&"), a.rfind(">"))
+    name = a[p+1:]
+    typ = a[:p+1].replace(" ","")
+    return tmap[typ]+"('"+name+"'"+((",'"+value+"'") if value else "")+")"
+
+def parse_fun(f,fun,namespace) :
+    iarg =fun.find("(")
+    earg =fun.rfind(")")
+    pre = fun[:iarg]
+    args = fun[iarg+1:earg].split(",")
+    w = pre.split()
+    t = w[1]
+    name = w[2]
+    ret = "None"
+    if t == "int" :
+        ret = "oint"
+    elif t != "void" :
+        raise NameError("Unknown return type : ", t)
+    if (args == ['']) :
+        args = []
+    if (name in ["initialize","setElements","addModelData"]) :
+        f.write("#")
+    f.write(namespace+".add("+",".join([ret,"'"+name+"'"]+[parse_arg(a) for a in args])+")\n")
+
+namespace = ["api"]
+
+with open("../Common/gmsh.h") as f :
+    with open("gen.py","w") as fo :
+        fo.write("from GenApi import *\n\napi = API()\n")
+        ls = f.readlines()
+        i = 0
+        while i < len(ls) :
+            l = ls[i].strip()
+            w = l.split()
+            i += 1
+            if not w :
+                continue
+            if w[0] == "GMSH_API" :
+                f = l
+                while f[-1] != ";" :
+                    l = ls[i].strip()
+                    i += 1
+                    f += " " + l
+                try :
+                    parse_fun(fo,f,namespace[-1])
+                except :
+                    raise NameError(f)
+            elif w[0] == "namespace" :
+                fo.write("\n"+w[1]+" = "+namespace[-1]+".add_module('"+w[1]+"')\n")
+                namespace += [w[1]]
+            elif w[0] == "}" :
+                namespace.pop()
+        fo.write("api.write_cpp()\n")
+        fo.write("api.write_c()\n")
+        fo.write("api.write_python()\n")
diff --git a/api/gen.py b/api/gen.py
index 8917e91b72..37c1e5f519 100644
--- a/api/gen.py
+++ b/api/gen.py
@@ -2,272 +2,157 @@ from GenApi import *
 
 api = API()
 
-#add_function("","Initialize",[iintp("argc"),arg("char **","argv")])
-gmsh = api.add_module("")
+gmsh = api.add_module('gmsh')
+#gmsh.add(None,'initialize',iint('argc','0'),icharpp('argv','0'))
+gmsh.add(None,'finalize')
+gmsh.add(None,'open',istring('fileName'))
+gmsh.add(None,'merge',istring('fileName'))
+gmsh.add(None,'write',istring('fileName'))
+gmsh.add(None,'clear')
 
-gmsh.add(None,"Finalize")
-gmsh.add(None,"Open",istring("fileName"))
-gmsh.add(None,"Merge",istring("fileName"))
-gmsh.add(None,"Export",istring("fileName"))
-gmsh.add(None,"Clear")
+option = gmsh.add_module('option')
+option.add(None,'setNumber',istring('name'),idouble('value'))
+option.add(None,'getNumber',istring('name'),odouble('value'))
+option.add(None,'setString',istring('name'),istring('value'))
+option.add(None,'getString',istring('name'),ostring('value'))
 
-options = api.add_module("Option")
-options.add(None,"SetNumber",istring("name"),idouble("value"))
-options.add(None,"GetNumber",istring("name"),odouble("value"))
-options.add(None,"SetString",istring("name"),istring("value"))
-options.add(None,"GetString",istring("name"),ostring("value"))
+model = gmsh.add_module('model')
+model.add(None,'add',istring('name'))
+model.add(None,'remove')
+model.add(None,'list',ovectorstring('names'))
+model.add(None,'setCurrent',istring('name'))
+model.add(None,'getEntities',ovectorpair('dimTags'),iint('dim','-1'))
+model.add(None,'getPhysicalGroups',ovectorpair('dimTags'),iint('dim','-1'))
+model.add(None,'getEntitiesForPhysicalGroup',iint('dim'),iint('tag'),ovectorint('tags'))
+model.add(oint,'addPhysicalGroup',iint('dim'),ivectorint('tags'),iint('tag','-1'))
+model.add(None,'setPhysicalName',iint('dim'),iint('tag'),istring('name'))
+model.add(None,'getPhysicalName',iint('dim'),iint('tag'),ostring('name'))
+model.add(None,'getBoundary',ivectorpair('dimTags'),ovectorpair('outDimTags'),ibool('combined','true'),ibool('oriented','true'),ibool('recursive','false'))
+model.add(None,'getEntitiesInBoundingBox',idouble('xmin'),idouble('ymin'),idouble('zmin'),idouble('xmax'),idouble('ymax'),idouble('zmax'),ovectorpair('tags'),iint('dim','-1'))
+model.add(None,'getBoundingBox',iint('dim'),iint('tag'),odouble('xmin'),odouble('ymin'),odouble('zmin'),odouble('xmax'),odouble('ymax'),odouble('zmax'))
+model.add(oint,'addDiscreteEntity',iint('dim'),iint('tag','-1'),ivectorint('boundary','std::vector<int>()'))
+model.add(None,'removeEntities',ivectorpair('dimTags'),ibool('recursive','false'))
 
-model = api.add_module("Model")
-model.add(None,"Create",istring("name"))
-model.add(None,"SetCurrent",istring("name"))
-model.add(None,"Delete")
+mesh = model.add_module('mesh')
+mesh.add(None,'generate',iint('dim'))
+mesh.add(None,'getLastEntityError',ovectorpair('dimTags'))
+mesh.add(None,'getLastVertexError',ovectorint('vertexTags'))
+mesh.add(None,'getVertices',iint('dim'),iint('tag'),ovectorint('vertexTags'),ovectordouble('coord'),ovectordouble('parametricCoord'))
+mesh.add(None,'getElements',iint('dim'),iint('tag'),ovectorint('types'),ovectorvectorint('elementTags'),ovectorvectorint('vertexTags'))
+mesh.add(None,'setVertices',iint('dim'),iint('tag'),ivectorint('vertexTags'),ivectordouble('coord'),ivectordouble('parametricCoord','std::vector<double>()'))
+#mesh.add(None,'setElements',iint('dim'),iint('tag'),ivectorint('types'),ivectorvectorint('elementTags'),ivectorvectorint('vertexTags'))
+mesh.add(None,'getVertex',iint('vertexTag'),ovectordouble('coord'),ovectordouble('parametricCoord'))
+mesh.add(None,'getElement',iint('elementTag'),oint('type'),ovectorint('vertexTags'))
+mesh.add(None,'setSize',ivectorpair('dimTags'),idouble('size'))
+mesh.add(None,'setTransfiniteLine',iint('tag'),iint('numVertices'),istring('type','"Progression"'),idouble('coef','1.'))
+mesh.add(None,'setTransfiniteSurface',iint('tag'),istring('arrangement','"Left"'),ivectorint('cornerTags','std::vector<int>()'))
+mesh.add(None,'setTransfiniteVolume',iint('tag'),ivectorint('cornerTags','std::vector<int>()'))
+mesh.add(None,'setRecombine',iint('dim'),iint('tag'))
+mesh.add(None,'setSmoothing',iint('dim'),iint('tag'),iint('val'))
+mesh.add(None,'setReverse',iint('dim'),iint('tag'),ibool('val','true'))
+mesh.add(None,'embed',iint('dim'),ivectorint('tags'),iint('inDim'),iint('inTag'))
 
-model.add(None,"GetEntities",ovectorpair("dimTags"),iint("dim","-1"))
-model.add(None,"GetPhysicalGroups",ovectorpair("dimTags"),iint("dim","-1"))
-model.add(oint,"AddPhysicalGroup",iint("dim"),ivectorint("tags"),iint("tag","-1"))
-model.add(None,"GetEntitiesForPhysicalGroup",iint("dim"),iint("tag"),ovectorint("tags"))
-model.add(None,"SetPhysicalName",iint("dim"),iint("tag"),istring("name"))
-model.add(None,"GetPhysicalName",iint("dim"),iint("tag"),ostring("name"))
-model.add(None,"GetBoundary",ivectorpair("inDimTags"),ovectorpair("outDimTags"),
-        ibool("combined","true"),ibool("oriented","true"),ibool("recursive","false"))
-model.add(None,"GetEntitiesInBoundingBox",
-        idouble("x1"),idouble("y1"),idouble("z1"),
-        idouble("x2"),idouble("y2"),idouble("z2"),
-        ovectorpair("tags"),iint("dim","-1"))
+field = mesh.add_module('field')
+field.add(oint,'add',istring('type'),iint('tag','-1'))
+field.add(None,'remove',iint('tag'))
+field.add(None,'setNumber',iint('tag'),istring('option'),idouble('value'))
+field.add(None,'setString',iint('tag'),istring('option'),istring('value'))
+field.add(None,'setNumbers',iint('tag'),istring('option'),ivectordouble('value'))
+field.add(None,'setAsBackground',iint('tag'))
 
-model.add(None,"GetBoundingBox",iint("dim"),iint("tag"),odouble("x1"),odouble("y1"),
-        odouble("z1"),odouble("x2"),odouble("y2"),odouble("z2"))
-model.add(None,"Remove",ivectorpair("dimTags"),ibool("recursive","false"))
-model.add(None,"Mesh",iint("dim"))
-model.add(None,"GetMeshVertices",iint("dim"),iint("tag"),
-        ovectorint("vertexTags"),
-        ovectordouble("coords"),
-        ovectordouble("parametricCoord")
-        )
-model.add(None,"GetMeshElements",iint("dim"),iint("tag"),
-        ovectorint("types"),
-        ovectorvectorint("elementTags"),
-        ovectorvectorint("vertexTags"))
-model.add(None,"SetMeshSize",ivectorpair("dimTags"),idouble("size"))
-model.add(None,"SetTransfiniteLine",iint("tag"),iint("nPoints"),
-        istring("type","Progression"),
-        idouble("coef","1."))
-model.add(None,"SetTransfiniteSurface",iint("tag"),
-        istring("arrangement","Left"),
-        ivectorint("cornerTags","std::vector<int>()"))
-model.add(None,"SetTransfiniteVolume",iint("tag"),
-        ivectorint("cornerTags","std::vector<int>()"))
-model.add(None,"SetSmoothing",iint("dim"),iint("tag"),iint("val"))
-model.add(None,"SetReverseMesh",iint("dim"),iint("tag"),ibool("val","true"))
-model.add(None,"Embed",iint("dim"),ivectorint("tags"),iint("inDim"),
-        iint("inTag"))
+geo = model.add_module('geo')
+geo.add(oint,'addPoint',idouble('x'),idouble('y'),idouble('z'),idouble('meshSize','0.'),iint('tag','-1'))
+geo.add(oint,'addLine',iint('startTag'),iint('endTag'),iint('tag','-1'))
+geo.add(oint,'addCircleArc',iint('startTag'),iint('centerTag'),iint('endTag'),iint('tag','-1'),idouble('nx','0.'),idouble('ny','0.'),idouble('nz','0.'))
+geo.add(oint,'addEllipseArc',iint('startTag'),iint('centerTag'),iint('majorTag'),iint('endTag'),iint('tag','-1'),idouble('nx','0.'),idouble('ny','0.'),idouble('nz','0.'))
+geo.add(oint,'addSpline',ivectorint('vertexTags'),iint('tag','-1'))
+geo.add(oint,'addBSpline',ivectorint('vertexTags'),iint('tag','-1'))
+geo.add(oint,'addBezier',ivectorint('vertexTags'),iint('tag','-1'))
+geo.add(oint,'addLineLoop',ivectorint('edgeTags'),iint('tag','-1'))
+geo.add(oint,'addPlaneSurface',ivectorint('wireTags'),iint('tag','-1'))
+geo.add(oint,'addSurfaceFilling',ivectorint('wireTags'),iint('tag','-1'),iint('sphereCenterTag','-1'))
+geo.add(oint,'addSurfaceLoop',ivectorint('faceTags'),iint('tag','-1'))
+geo.add(oint,'addVolume',ivectorint('shellTags'),iint('tag','-1'))
+geo.add(None,'extrude',ivectorpair('dimTags'),idouble('dx'),idouble('dy'),idouble('dz'),ovectorpair('outDimTags'),ivectorint('numElements','std::vector<int>()'),ivectordouble('heights','std::vector<double>()'),ibool('recombine','false'))
+geo.add(None,'revolve',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('ax'),idouble('ay'),idouble('az'),idouble('angle'),ovectorpair('outDimTags'),ivectorint('numElements','std::vector<int>()'),ivectordouble('heights','std::vector<double>()'),ibool('recombine','false'))
+geo.add(None,'twist',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),idouble('dz'),idouble('ax'),idouble('ay'),idouble('az'),idouble('angle'),ovectorpair('outDimTags'),ivectorint('numElements','std::vector<int>()'),ivectordouble('heights','std::vector<double>()'),ibool('recombine','false'))
+geo.add(None,'translate',ivectorpair('dimTags'),idouble('dx'),idouble('dy'),idouble('dz'))
+geo.add(None,'rotate',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('ax'),idouble('ay'),idouble('az'),idouble('angle'))
+geo.add(None,'dilate',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('a'),idouble('b'),idouble('c'))
+geo.add(None,'symmetry',ivectorpair('dimTags'),idouble('a'),idouble('b'),idouble('c'),idouble('d'))
+geo.add(None,'copy',ivectorpair('dimTags'),ovectorpair('outDimTags'))
+geo.add(None,'remove',ivectorpair('dimTags'),ibool('recursive','false'))
+geo.add(None,'removeAllDuplicates')
+geo.add(None,'synchronize')
 
-model_geo = api.add_module("ModelGeo")
-model_geo.add(oint,"AddPoint",idouble("x"),idouble("y"), idouble("z"),idouble("meshSize","0."),iint("tag","-1"))
-model_geo.add(oint,"AddLine",iint("startTag"),iint("endTag"),iint("tag","-1"))
-model_geo.add(oint,"AddCircleArc",
-        iint("startTag"), iint("centerTag"),iint("endTag"),
-        iint("tag","-1"),
-        idouble("nx","0."),idouble("ny","0."), idouble("nz","0."))
-model_geo.add(oint,"AddEllipseArc",
-        iint("startTag"),iint("centerTag"),iint("majorTag"),iint("endTag"),
-        iint("tag","-1"),
-        idouble("nx","0."),idouble("ny","0."), idouble("nz","0."))
-model_geo.add(oint,"AddSpline",ivectorint("vertexTags"),iint("tag","-1"))
-model_geo.add(oint,"AddBSpline",ivectorint("vertexTags"),iint("tag","-1"))
-model_geo.add(oint,"AddBezier",ivectorint("vertexTags"),iint("tag","-1"))
-model_geo.add(oint,"AddLineLoop",ivectorint("edgeTags"),iint("tag","-1"))
-model_geo.add(oint,"AddPlaneSurface",ivectorint("wireTags"),iint("tag","-1"))
-model_geo.add(oint,"AddSurfaceFilling",ivectorint("wireTags"), iint("sphereCenterTag","-1"),iint("tag","-1"))
-model_geo.add(oint,"AddSurfaceLoop",ivectorint("faceTags"),iint("tag","-1"))
-model_geo.add(oint,"AddVolume",ivectorint("shellTags"),iint("tag","-1"))
-model_geo.add(None,"Extrude",ivectorpair("inDimTags"),
-        idouble("dx"),idouble("dy"),idouble("dz"),
-        ovectorpair("outDimTags"),
-        ivectorint("numElements","std::vector<int>()"),
-        ivectordouble("heights","std::vector<double>()"),
-        ibool("recombine","false"))
-model_geo.add(None,"Revolve",ivectorpair("inDimTags"),
-        idouble("x"),idouble("y"),idouble("z"),
-        idouble("ax"),idouble("ay"),
-        idouble("az"),idouble("angle"),
-        ovectorpair("outDimTags"),
-        ivectorint("numElements","std::vector<int>()"),
-        ivectordouble("heights","std::vector<double>()"),
-        ibool("recombine","false"))
-model_geo.add(None,"Twist",ivectorpair("inDimTags"),
-        idouble("x"),idouble("y"),idouble("z"),
-        idouble("dx"),idouble("dy"),idouble("dz"),
-        idouble("ax"),idouble("ay"),idouble("az"),
-        idouble("angle"),
-        ovectorpair("outDimTags"),
-        ivectorint("numElements","std::vector<int>()"),
-        ivectordouble("heights","std::vector<double>()"),
-        ibool("recombine","false"))
-model_geo.add(None,"Translate",ivectorpair("dimTags"),
-        idouble("dx"),idouble("dy"),idouble("dz"))
-model_geo.add(None,"Rotate",ivectorpair("dimTags"),idouble("x"),idouble("y"),
-        idouble("z"),idouble("ax"),idouble("ay"),
-        idouble("az"),idouble("angle"))
-model_geo.add(None,"Dilate",ivectorpair("dimTags"),idouble("x"),idouble("y"),
-        idouble("z"),idouble("a"),idouble("b"),
-        idouble("c"))
-model_geo.add(None,"Symmetry",ivectorpair("dimTags"),idouble("a"),idouble("b"),
-        idouble("c"),idouble("d"))
-model_geo.add(None,"Copy",ivectorpair("inDimTags"),ovectorpair("outDimTags"))
-model_geo.add(None,"Remove",ivectorpair("dimTags"),ibool("recursive","false"))
-model_geo.add(None,"RemoveAllDuplicates")
-model_geo.add(None,"SetMeshSize",ivectorpair("dimTags"),idouble("size"))
-model_geo.add(None,"SetTransfiniteLine",iint("tag"),iint("nPoints"),
-        istring("type","Progression"),
-        idouble("coef","1."))
-model_geo.add(None,"SetTransfiniteSurface",iint("tag"),
-        istring("arrangement","Left"),
-        ivectorint("cornerTags","std::vector<int>()"))
-model_geo.add(None,"SetTransfiniteVolume",iint("tag"),
-        ivectorint("cornerTags","std::vector<int>()"))
-model_geo.add(None,"SetRecombine",iint("dim"),iint("tag"),idouble("angle","45."))
-model_geo.add(None,"SetSmoothing",iint("dim"),iint("tag"),iint("val"))
-model_geo.add(None,"SetReverseMesh",iint("dim"),iint("tag"),ibool("val","true"))
-model_geo.add(None,"Synchronize")
+mesh = geo.add_module('mesh')
+mesh.add(None,'setSize',ivectorpair('dimTags'),idouble('size'))
+mesh.add(None,'setTransfiniteLine',iint('tag'),iint('nPoints'),istring('type','"Progression"'),idouble('coef','1.'))
+mesh.add(None,'setTransfiniteSurface',iint('tag'),istring('arrangement','"Left"'),ivectorint('cornerTags','std::vector<int>()'))
+mesh.add(None,'setTransfiniteVolume',iint('tag'),ivectorint('cornerTags','std::vector<int>()'))
+mesh.add(None,'setRecombine',iint('dim'),iint('tag'),idouble('angle','45.'))
+mesh.add(None,'setSmoothing',iint('dim'),iint('tag'),iint('val'))
+mesh.add(None,'setReverse',iint('dim'),iint('tag'),ibool('val','true'))
 
-model_occ = api.add_module("ModelOcc")
-#model_occ.add(oint,"AddPoint",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("meshSize","0."))
-#model_occ.add(oint,"AddLine",iint("tag"),iint("startTag"),iint("endTag"))
-#model_occ.add(oint,"AddCircleArc",iint("tag"),iint("startTag"),iint("centerTag"),
-#        iint("endTag"))
-#model_occ.add(oint,"AddCircle",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("r"),
-#        idouble("angle1","0."),idouble("angle2","2*M_PI"))
-#model_occ.add(oint,"AddEllipseArc",iint("tag"),iint("startTag"),iint("centerTag"),
-#        iint("endTag"))
-#model_occ.add(oint,"AddEllipse",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("r1"),idouble("r2"),
-#        idouble("angle1","0."),
-#        idouble("angle2","2*M_PI"))
-#model_occ.add(oint,"AddSpline",iint("tag"),ivectorint("vertexTags"))
-#model_occ.add(oint,"AddBezier",iint("tag"),ivectorint("vertexTags"))
-#model_occ.add(oint,"AddBSpline",iint("tag"),ivectorint("vertexTags"))
-#model_occ.add(oint,"AddWire",iint("tag"),ivectorint("edgeTags"),
-#        ibool("checkClosed","false"))
-#model_occ.add(oint,"AddLineLoop",iint("tag"),ivectorint("edgeTags"))
-#model_occ.add(oint,"AddRectangle",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("dx"),idouble("dy"),
-#        idouble("roundedRadius","0."))
-#model_occ.add(oint,"AddDisk",iint("tag"),idouble("xc"),idouble("yc"),
-#        idouble("zc"),idouble("rx"),idouble("ry"))
-#model_occ.add(oint,"AddPlaneSurface",iint("tag"),ivectorint("wireTags"))
-#model_occ.add(oint,"AddSurfaceFilling",iint("tag"),iint("wireTag"))
-#model_occ.add(oint,"AddSurfaceLoop",iint("tag"),ivectorint("faceTags"))
-#model_occ.add(oint,"AddVolume",iint("tag"),ivectorint("shellTags"))
-#model_occ.add(oint,"AddSphere",iint("tag"),idouble("xc"),idouble("yc"),
-#        idouble("zc"),idouble("radius"),
-#        idouble("angle1","-M_PI/2"),
-#        idouble("angle2","M_PI/2"),
-#        idouble("angle3","2*M_PI"))
-#model_occ.add(oint,"AddBox",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("dx"),idouble("dy"),
-#        idouble("dz"))
-#model_occ.add(oint,"AddCylinder",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("dx"),idouble("dy"),
-#        idouble("dz"),idouble("r"),
-#        idouble("angle","2*M_PI"))
-#model_occ.add(oint,"AddCone",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("dx"),idouble("dy"),
-#        idouble("dz"),idouble("r1"),idouble("r2"),
-#        idouble("angle","2*M_PI"))
-#model_occ.add(oint,"AddWedge",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("dx"),idouble("dy"),
-#        idouble("dz"),idouble("ltx","0."))
-#model_occ.add(oint,"AddTorus",iint("tag"),idouble("x"),idouble("y"),
-#        idouble("z"),idouble("r1"),idouble("r2"),
-#        idouble("angle","2*M_PI"))
-#model_occ.add(oint,"AddThruSections",ivectorint("wireTags"),
-#        ovectorpair("outDimTags"),
-#        iint("tag"),
-#        ibool("makeSolid","true"),
-#        ibool("makeRuled","false"))
-#GMSH_API addThickSolid"",iint("tag"),iint("solidTag"),
-#                       ivectorint("excludeFaceTags"),
-#                       idouble("offset"),ovectorpair("outDimTags"))
-model_occ.add(None,"Extrude",ivectorpair("inDimTags"),idouble("dx"),idouble("dy"),
-        idouble("dz"),ovectorpair("outDimTags"),
-        ivectorint("numElements","std::vector<int>()"),
-        ivectordouble("heights","std::vector<double>()"),
-        ibool("recombine","false"))
-model_occ.add(None,"Revolve",ivectorpair("inDimTags"),
-        idouble("x"),idouble("y"),idouble("z"),
-        idouble("ax"),idouble("ay"),idouble("az"),
-        idouble("angle"),ovectorpair("outDimTags"),
-        ivectorint("numElements","std::vector<int>()"),
-        ivectordouble("heights","std::vector<double>()"),
-        ibool("recombine","false"))
-model_occ.add(None,"AddPipe",ivectorpair("inDimTags"),iint("wireTag"),
-        ovectorpair("outDimTags"))
-model_occ.add(None,"Fillet",ivectorint("regionTags"),
-        ivectorint("edgeTags"),
-        idouble("radius"),ovectorpair("outDimTags"),
-        ibool("removeRegion","true"))
-model_occ.add(oint,"BooleanUnion",ivectorpair("objectDimTags"),
-        ivectorpair("toolDimTags"),
-        ovectorpair("outDimTags"),
-        ovectorvectorpair("outDimTagsMap"),
-        iint("tag","-1"),
-        ibool("removeObject","true"),
-        ibool("removeTool","true"))
-model_occ.add(oint,"BooleanIntersection",ivectorpair("objectDimTags"),
-        ivectorpair("toolDimTags"),
-        ovectorpair("outDimTags"),
-        ovectorvectorpair("outDimTagsMap"),
-        iint("tag"),
-        ibool("removeObject","true"),
-        ibool("removeTool","true"))
-model_occ.add(oint,"BooleanDifference",ivectorpair("objectDimTags"),
-        ivectorpair("toolDimTags"),
-        ovectorpair("outDimTags"),
-        ovectorvectorpair("outDimTagsMap"),
-        iint("tag","-1"),
-        ibool("removeObject","true"),
-        ibool("removeTool","true"))
-model_occ.add(oint,"BooleanFragments",ivectorpair("objectDimTags"),
-        ivectorpair("toolDimTags"),
-        ovectorpair("outDimTags"),
-        ovectorvectorpair("outDimTagsMap"),
-        iint("tag","-1"),
-        ibool("removeObject","true"),
-        ibool("removeTool","true"))
-model_occ.add(None,"Translate",ivectorpair("dimTags"),idouble("dx"),
-        idouble("dy"),idouble("dz"))
-model_occ.add(None,"Rotate",ivectorpair("dimTags"),idouble("x"),
-        idouble("y"),idouble("z"),idouble("ax"),
-        idouble("ay"),idouble("az"),idouble("angle"))
-model_occ.add(None,"Dilate",ivectorpair("dimTags"),idouble("x"),
-        idouble("y"),idouble("z"),idouble("a"),
-        idouble("b"),idouble("c"))
-model_occ.add(None,"Symmetry",ivectorpair("dimTags"),idouble("a"),
-        idouble("b"),idouble("c"),idouble("d"))
-model_occ.add(None,"Copy",ivectorpair("inDimTags"),ovectorpair("outDimTags"))
-model_occ.add(None,"Remove",ivectorpair("dimTags"),ibool("recursive","false"))
-model_occ.add(None,"RemoveAllDuplicates")
-model_occ.add(None,"ImportShapes",istring("fileName"),ovectorpair("outDimTags"),
-        ibool("highestDimOnly","true"),
-        istring("format",""))
-model_occ.add(None,"SetMeshSize",ivectorpair("dimTags"),idouble("size"))
-model_occ.add(None,"Synchronize")
+occ = model.add_module('occ')
+occ.add(oint,'addPoint',idouble('x'),idouble('y'),idouble('z'),idouble('meshSize','0.'),iint('tag','-1'))
+occ.add(oint,'addLine',iint('startTag'),iint('endTag'),iint('tag','-1'))
+occ.add(oint,'addCircleArc',iint('startTag'),iint('centerTag'),iint('endTag'),iint('tag','-1'))
+occ.add(oint,'addCircle',idouble('x'),idouble('y'),idouble('z'),idouble('r'),iint('tag','-1'),idouble('angle1','0.'),idouble('angle2','2*M_PI'))
+occ.add(oint,'addEllipseArc',iint('startTag'),iint('centerTag'),iint('endTag'),iint('tag','-1'))
+occ.add(oint,'addEllipse',idouble('x'),idouble('y'),idouble('z'),idouble('r1'),idouble('r2'),iint('tag','-1'),idouble('angle1','0.'),idouble('angle2','2*M_PI'))
+occ.add(oint,'addSpline',ivectorint('vertexTags'),iint('tag','-1'))
+occ.add(oint,'addBezier',ivectorint('vertexTags'),iint('tag','-1'))
+occ.add(oint,'addBSpline',ivectorint('vertexTags'),iint('tag','-1'))
+occ.add(oint,'addWire',ivectorint('edgeTags'),iint('tag','-1'),ibool('checkClosed','false'))
+occ.add(oint,'addLineLoop',ivectorint('edgeTags'),iint('tag','-1'))
+occ.add(oint,'addRectangle',idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),iint('tag','-1'),idouble('roundedRadius','0.'))
+occ.add(oint,'addDisk',idouble('xc'),idouble('yc'),idouble('zc'),idouble('rx'),idouble('ry'),iint('tag','-1'))
+occ.add(oint,'addPlaneSurface',ivectorint('wireTags'),iint('tag','-1'))
+occ.add(oint,'addSurfaceFilling',iint('wireTag'),iint('tag','-1'))
+occ.add(oint,'addSurfaceLoop',ivectorint('faceTags'),iint('tag','-1'))
+occ.add(oint,'addVolume',ivectorint('shellTags'),iint('tag','-1'))
+occ.add(oint,'addSphere',idouble('xc'),idouble('yc'),idouble('zc'),idouble('radius'),iint('tag','-1'),idouble('angle1','-M_PI/2'),idouble('angle2','M_PI/2'),idouble('angle3','2*M_PI'))
+occ.add(oint,'addBox',idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),idouble('dz'),iint('tag','-1'))
+occ.add(oint,'addCylinder',idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),idouble('dz'),idouble('r'),iint('tag','-1'),idouble('angle','2*M_PI'))
+occ.add(oint,'addCone',idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),idouble('dz'),idouble('r1'),idouble('r2'),iint('tag','-1'),idouble('angle','2*M_PI'))
+occ.add(oint,'addWedge',idouble('x'),idouble('y'),idouble('z'),idouble('dx'),idouble('dy'),idouble('dz'),iint('tag','-1'),idouble('ltx','0.'))
+occ.add(oint,'addTorus',idouble('x'),idouble('y'),idouble('z'),idouble('r1'),idouble('r2'),iint('tag','-1'),idouble('angle','2*M_PI'))
+occ.add(oint,'addThruSections',ivectorint('wireTags'),ovectorpair('outDimTags'),iint('tag','-1'),ibool('makeSolid','true'),ibool('makeRuled','false'))
+occ.add(oint,'addThickSolid',iint('solidTag'),ivectorint('excludeFaceTags'),idouble('offset'),ovectorpair('outDimTags'),iint('tag','-1'))
+occ.add(None,'extrude',ivectorpair('dimTags'),idouble('dx'),idouble('dy'),idouble('dz'),ovectorpair('outDimTags'),ivectorint('numElements','std::vector<int>()'),ivectordouble('heights','std::vector<double>()'),ibool('recombine','false'))
+occ.add(None,'revolve',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('ax'),idouble('ay'),idouble('az'),idouble('angle'),ovectorpair('outDimTags'),ivectorint('numElements','std::vector<int>()'),ivectordouble('heights','std::vector<double>()'),ibool('recombine','false'))
+occ.add(None,'addPipe',ivectorpair('dimTags'),iint('wireTag'),ovectorpair('outDimTags'))
+occ.add(None,'fillet',ivectorint('regionTags'),ivectorint('edgeTags'),idouble('radius'),ovectorpair('outDimTags'),ibool('removeRegion','true'))
+occ.add(oint,'booleanUnion',ivectorpair('objectDimTags'),ivectorpair('toolDimTags'),ovectorpair('outDimTags'),ovectorvectorpair('outDimTagsMap'),iint('tag','-1'),ibool('removeObject','true'),ibool('removeTool','true'))
+occ.add(oint,'booleanIntersection',ivectorpair('objectDimTags'),ivectorpair('toolDimTags'),ovectorpair('outDimTags'),ovectorvectorpair('outDimTagsMap'),iint('tag','-1'),ibool('removeObject','true'),ibool('removeTool','true'))
+occ.add(oint,'booleanDifference',ivectorpair('objectDimTags'),ivectorpair('toolDimTags'),ovectorpair('outDimTags'),ovectorvectorpair('outDimTagsMap'),iint('tag','-1'),ibool('removeObject','true'),ibool('removeTool','true'))
+occ.add(oint,'booleanFragments',ivectorpair('objectDimTags'),ivectorpair('toolDimTags'),ovectorpair('outDimTags'),ovectorvectorpair('outDimTagsMap'),iint('tag','-1'),ibool('removeObject','true'),ibool('removeTool','true'))
+occ.add(None,'translate',ivectorpair('dimTags'),idouble('dx'),idouble('dy'),idouble('dz'))
+occ.add(None,'rotate',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('ax'),idouble('ay'),idouble('az'),idouble('angle'))
+occ.add(None,'dilate',ivectorpair('dimTags'),idouble('x'),idouble('y'),idouble('z'),idouble('a'),idouble('b'),idouble('c'))
+occ.add(None,'symmetry',ivectorpair('dimTags'),idouble('a'),idouble('b'),idouble('c'),idouble('d'))
+occ.add(None,'copy',ivectorpair('dimTags'),ovectorpair('outDimTags'))
+occ.add(None,'remove',ivectorpair('dimTags'),ibool('recursive','false'))
+occ.add(None,'removeAllDuplicates')
+occ.add(None,'importShapes',istring('fileName'),ovectorpair('outDimTags'),ibool('highestDimOnly','true'),istring('format','""'))
+occ.add(None,'setMeshSize',ivectorpair('dimTags'),idouble('size'))
+occ.add(None,'synchronize')
 
-model_field = api.add_module("ModelField")
-model_field.add(oint,"Create",istring("type"),iint("tag","-1"))
-model_field.add(None,"SetNumber",iint("tag"),istring("option"),idouble("value"))
-model_field.add(None,"SetString",iint("tag"),istring("option"),istring("value"))
-model_field.add(None,"SetNumbers",iint("tag"),istring("option"),ivectordouble("value"))
-model_field.add(None,"SetAsBackground",iint("tag"))
-model_field.add(None,"Delete",iint("tag"))
+view = gmsh.add_module('view')
+view.add(oint,'add',istring('name'),iint('tag','-1'))
+view.add(None,'remove',iint('tag'))
+view.add(oint,'getIndex',iint('tag'))
+view.add(None,'getTags',ovectorint('tags'))
+#view.add(None,'addModelData',iint('tag'),istring('modelName'),istring('dataType'),ivectorint('tags'),ivectorvectordouble('data'),iint('step','0'),iint('time','0.'),iint('numComponents','-1'),iint('partition','0'))
+view.add(None,'addListData',iint('tag'),istring('type'),iint('numEle'),ivectordouble('data'))
+view.add(None,'probe',iint('tag'),idouble('x'),idouble('y'),idouble('z'),ovectordouble('value'),iint('step','-1'),iint('numComp','-1'),ibool('gradient','false'),idouble('tolerance','0.'),ivectordouble('xElemCoord','std::vector<double>()'),ivectordouble('yElemCoord','std::vector<double>()'),ivectordouble('zElemCoord','std::vector<double>()'))
+view.add(None,'write',iint('tag'),istring('fileName'),ibool('append','false'))
 
-api.add_module("View")
-api.add_module("Plugin")
-api.add_module("Graphics")
-
-api.write_cpp("gmsh")
-api.write_c("gmshc")
+plugin = gmsh.add_module('plugin')
+plugin.add(None,'setNumber',istring('name'),istring('option'),idouble('value'))
+plugin.add(None,'setString',istring('name'),istring('option'),istring('value'))
+plugin.add(None,'run',istring('name'))
+api.write_cpp()
+api.write_c()
 api.write_python()
diff --git a/api/main.c b/api/main.c
index 9d3405c10c..7baa31cc15 100644
--- a/api/main.c
+++ b/api/main.c
@@ -1,26 +1,26 @@
 #include <stdio.h>
 #include "gmshc.h"
 
-#define chk(ierr) if (ierr != 0) {fprintf(stderr, "ERROR on line %i in function '%s': gmsh function return non-zero error code: %i\n",__LINE__, __FUNCTION__,ierr); gmshcFinalize(NULL); exit(ierr);}
+#define chk(ierr) if (ierr != 0) {fprintf(stderr, "ERROR on line %i in function '%s': gmsh function return non-zero error code: %i\n",__LINE__, __FUNCTION__,ierr); gmshFinalize(NULL); exit(ierr);}
 
 void genGeometry() {
   int ierr;
-  gmshcModelCreate("square",&ierr);chk(ierr);
-  gmshcModelGeoAddPoint(0,0,0,0.1,1,&ierr);chk(ierr);
-  gmshcModelGeoAddPoint(1,0,0,0.1,2,&ierr);chk(ierr);
-  gmshcModelGeoAddPoint(1,1,0,0.1,3,&ierr);chk(ierr);
-  gmshcModelGeoAddPoint(0,1,0,0.1,4,&ierr);chk(ierr);
-  gmshcModelGeoAddLine(1,2,1,&ierr); chk(ierr);
-  gmshcModelGeoAddLine(2,3,2,&ierr); chk(ierr);
-  gmshcModelGeoAddLine(3,4,3,&ierr); chk(ierr);
+  gmshModelAdd("square",&ierr);chk(ierr);
+  gmshModelGeoAddPoint(0,0,0,0.1,1,&ierr);chk(ierr);
+  gmshModelGeoAddPoint(1,0,0,0.1,2,&ierr);chk(ierr);
+  gmshModelGeoAddPoint(1,1,0,0.1,3,&ierr);chk(ierr);
+  gmshModelGeoAddPoint(0,1,0,0.1,4,&ierr);chk(ierr);
+  gmshModelGeoAddLine(1,2,1,&ierr); chk(ierr);
+  gmshModelGeoAddLine(2,3,2,&ierr); chk(ierr);
+  gmshModelGeoAddLine(3,4,3,&ierr); chk(ierr);
   // try automatic assignement of tag
-  int line4 = gmshcModelGeoAddLine(4,1,-1,&ierr); chk(ierr);
+  int line4 = gmshModelGeoAddLine(4,1,-1,&ierr); chk(ierr);
   printf("line4 received tag %i\n\n", line4);
   int ll[] = {1,2,3,line4};
-  gmshcModelGeoAddLineLoop(ll,4,1,&ierr); chk(ierr);
+  gmshModelGeoAddLineLoop(ll,4,1,&ierr); chk(ierr);
   int s[] = {1};
-  gmshcModelGeoAddPlaneSurface(ll,1,6,&ierr); chk(ierr);
-  gmshcModelGeoSynchronize(&ierr); chk(ierr);
+  gmshModelGeoAddPlaneSurface(ll,1,6,&ierr); chk(ierr);
+  gmshModelGeoSynchronize(&ierr); chk(ierr);
 }
 
 void printMesh() {
@@ -28,13 +28,13 @@ void printMesh() {
   int *dimTags;
   size_t ndimTags;
 
-  gmshcModelGetEntities(&dimTags, &ndimTags, -1,&ierr); chk(ierr);
+  gmshModelGetEntities(&dimTags, &ndimTags, -1,&ierr); chk(ierr);
 
   for (size_t ie = 0; ie < ndimTags/2; ++ie) {
     int *types, **elementTags, **vertexTags;
     size_t ntypes, *nelementTags, nnelementTags, *nvertexTags, nnvertexTags;
 
-    gmshcModelGetMeshElements(dimTags[ie*2+0], dimTags[ie*2+1], &types, &ntypes, &elementTags, &nelementTags, &nnelementTags, &vertexTags, &nvertexTags, &nnvertexTags,&ierr); chk(ierr);
+    gmshModelMeshGetElements(dimTags[ie*2+0], dimTags[ie*2+1], &types, &ntypes, &elementTags, &nelementTags, &nnelementTags, &vertexTags, &nvertexTags, &nnvertexTags,&ierr); chk(ierr);
 
     printf("entity %i of dim %i\n", dimTags[ie*2+1], dimTags[ie*2+0]);
     for (size_t i = 0; i < nnelementTags; ++i) {
@@ -65,16 +65,16 @@ void printMesh() {
 void genError() {
   int ierr;
   printf("\n** generate an error **\n");
-  gmshcModelGetMeshElements(999, 999, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&ierr); chk(ierr);
+  gmshModelMeshGetElements(999, 999, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&ierr); chk(ierr);
 }
 
 int main(int argc, char **argv) {
   int ierr;
-  gmshcInitialize(argc, argv);
+  gmshInitialize(argc, argv);
   genGeometry();
-  gmshcModelMesh(2,&ierr); chk(ierr);
-  gmshcExport("square.msh",&ierr); chk(ierr);
+  gmshModelMeshGenerate(2,&ierr); chk(ierr);
+  gmshWrite("square.msh",&ierr); chk(ierr);
   printMesh();
   genError();
-  gmshcFinalize(&ierr); chk(ierr);
+  gmshFinalize(&ierr); chk(ierr);
 }
diff --git a/api/test.py b/api/test.py
index 76e99afec5..6021727d4c 100644
--- a/api/test.py
+++ b/api/test.py
@@ -1,48 +1,51 @@
 import gmsh
 
-gmsh.Initialize()
-gmsh.Open("square.msh")
-
-gmsh.ModelCreate("square")
-gmsh.ModelGeoAddPoint(0,0,0,0.1,1)
-gmsh.ModelGeoAddPoint(1,0,0,0.1,2)
-gmsh.ModelGeoAddPoint(1,1,0,0.1,3)
-gmsh.ModelGeoAddPoint(0,1,0,0.1,4)
-gmsh.ModelGeoAddLine(1,2,1)
-gmsh.ModelGeoAddLine(2,3,2)
-gmsh.ModelGeoAddLine(3,4,3)
-line4 = gmsh.ModelGeoAddLine(4,1,-1)
+gmsh.initialize()
+gmsh.open("square.msh")
+
+model = gmsh.model
+
+model.add("square")
+factory = model.geo
+factory.addPoint(0,0,0,0.1,1)
+factory.addPoint(1,0,0,0.1,2)
+factory.addPoint(1,1,0,0.1,3)
+factory.addPoint(0,1,0,0.1,4)
+factory.addLine(1,2,1)
+factory.addLine(2,3,2)
+factory.addLine(3,4,3)
+line4 = factory.addLine(4,1,-1)
 print("line4 received tag ", line4)
-gmsh.ModelGeoAddLineLoop([1,2,3,line4],1)
-gmsh.ModelGeoAddPlaneSurface([1],6)
-gmsh.ModelGeoSynchronize()
+factory.addLineLoop([1,2,3,line4],1)
+factory.addPlaneSurface([1],6)
+factory.synchronize()
 
-ptag = gmsh.ModelAddPhysicalGroup(1,[1,2,3,4],-1)
-ent = gmsh.ModelGetEntitiesForPhysicalGroup(1,ptag)
+ptag = model.addPhysicalGroup(1,[1,2,3,4],-1)
+ent = model.getEntitiesForPhysicalGroup(1,ptag)
 print("new physical group ",ptag,":",ent, type(ent))
 
-gmsh.ModelAddPhysicalGroup(2,[6],-1)
+model.addPhysicalGroup(2,[6],-1)
 
-print(gmsh.OptionGetString("General.BuildOptions"))
-print(gmsh.OptionGetNumber("Mesh.Algorithm"))
-gmsh.OptionSetNumber("Mesh.Algorithm", 3.0)
-print(gmsh.OptionGetNumber("Mesh.Algorithm"))
-gmsh.ModelMesh(2)
-gmsh.Export("square.msh")
+print(gmsh.option.getString("General.BuildOptions"))
+print(gmsh.option.getNumber("Mesh.Algorithm"))
+gmsh.option.setNumber("Mesh.Algorithm", 3.0)
+print(gmsh.option.getNumber("Mesh.Algorithm"))
+model.mesh.generate(2)
+
+gmsh.write("square.msh")
 
 print("Entities")
-entities = gmsh.ModelGetEntities(-1)
+entities = model.getEntities(-1)
 for e in entities :
     print("entity ",e)
-    types,tags,vertices = gmsh.ModelGetMeshElements(e[0],e[1])
+    types,tags,vertices = model.mesh.getElements(e[0],e[1])
     for i in range(len(types)):
         print("type ", types[i])
         print("tags : ", list(tags[i]))
         print("vertices : ", list(vertices[i]))
 
-
 print("Vertices")
-tags, coord, _ = gmsh.ModelGetMeshVertices(2,6)
+tags, coord, _ = model.mesh.getVertices(2,6)
 print(tags)
 print(coord)
-gmsh.Finalize()
+gmsh.finalize()
-- 
GitLab