Skip to content
Snippets Groups Projects
Select Git revision
  • 34f3d76195a03f889320866ce29e68ab1cbef1e2
  • master default
  • cgnsUnstructured
  • partitioning
  • poppler
  • HighOrderBLCurving
  • gmsh_3_0_4
  • gmsh_3_0_3
  • gmsh_3_0_2
  • gmsh_3_0_1
  • gmsh_3_0_0
  • gmsh_2_16_0
  • gmsh_2_15_0
  • gmsh_2_14_1
  • gmsh_2_14_0
  • gmsh_2_13_2
  • gmsh_2_13_1
  • gmsh_2_12_0
  • gmsh_2_11_0
  • gmsh_2_10_1
  • gmsh_2_10_0
  • gmsh_2_9_3
  • gmsh_2_9_2
  • gmsh_2_9_1
  • gmsh_2_9_0
  • gmsh_2_8_6
26 results

LuaBindings.h

Blame
  • Forked from gmsh / gmsh
    Source project has a limited visibility.
    LuaBindings.h 27.76 KiB
    #ifndef _LUA_BINDINGS_H_
    #define _LUA_BINDINGS_H_
    
    #include <map>
    #include <vector>
    #include <set>
    #include "GmshConfig.h"
    #include "GmshMessage.h"
    #include "Bindings.h"
    
    #ifdef HAVE_LUA
    
    extern "C" {
    #include "lua.h"
    #include "lauxlib.h"
    }
    /*** store a unique static class name for each binded class ***/
    template <typename type>
    class className{
      static std::string _name;
      public:
      static void set(std::string name){
        if(_name!=""){
          throw;
        }
        _name=name;
      }
      static const std::string &get(){
        if(_name==""){
          Msg::Error("Class unknown to Lua");
          throw;
        }
        return _name;
      }
    };
    template<typename type>
    std::string  className<type>::_name;
    
    template <>
    template <typename t>
    class className<t*>{
      public:
      static const std::string get(){
        return className<t>::get();
      }
    };
    template <typename t>
    class className<const t &>{
      public:
      static const std::string get(){
        return className<t>::get();
      }
    };
    
    
    class classBinding;
    class binding {
      static binding *_instance;
      void checkDocCompleteness();
      public:
      inline static binding *instance(){return _instance ? _instance : new binding();}
      lua_State *L;
      int readFile(const char *filename);
      void interactiveSession();
      binding();
      std::map<std::string,classBinding *> classes;
      template<class t>
      classBinding *addClass(std::string className);
    };
    
    template <>
    class className<lua_State>{
      public:
      static const std::string get(){
        return "-1";
      }
    };
    
    
    
    /*** lua Stack : templates to get/push value from/on the lua stack ***/
    
    template<class type>
    class luaStack {
    };
    
    template <>
    class luaStack<void>
    {
      public:
      static std::string getName(){
        return "void";
      }
    };
    
    template<>
    class luaStack<lua_State *>{
      public:
      static lua_State *get(lua_State *L, int ia){
        return L;
      }
      static std::string getName(){
        return "-1";
      }
    };
    
    template<>
    class luaStack<int>{
      public:
      static int get(lua_State *L, int ia){
        int a= luaL_checkint(L,ia);
        return a;
      }
      static void push(lua_State *L, int i){
        lua_pushinteger(L,i);
      }
      static std::string getName(){
        return "int";
      }
    };
    
    template<>
    class luaStack<unsigned int>{
      public:
      static int get(lua_State *L, unsigned int ia){
        unsigned int a= (unsigned int)luaL_checkint(L,ia);
        return a;
      }
      static void push(lua_State *L, unsigned int i){
        lua_pushinteger(L,i);
      }
      static std::string getName(){
        return "unsigned int";
      }
    };
    
    template<class type>
    class luaStack<std::vector<type > >{
      public:
      static std::vector<type>  get(lua_State *L, int ia){
        std::vector<type> v;
        size_t size=lua_objlen(L,ia);
        v.resize(size);
        for(size_t i=0;i<size;i++){
          lua_rawgeti(L, ia, i+1);
          v[i]=luaStack<type>::get(L,-1);
          lua_pop(L,1);
        }
        return v;
      }
      static void push(lua_State *L, const std::vector<type>& v){
        lua_createtable(L, v.size(), 0);
        for(size_t i=0;i<v.size;i++){
          luaStack<type>::push(L,v[i]);
          lua_rawseti(L, 2, i+1);
        }
      }
      static std::string getName(){
        std::string name="vector of ";
        return name+luaStack<type>::getName();
      }
    };
    
    template<>
    class luaStack<double>{
      public:
      static double get(lua_State *L, int ia){
        return luaL_checknumber(L,ia);
      }
      static void push(lua_State *L, double v){
        lua_pushnumber(L,v);
      }
      static std::string getName(){
        return "double";
      }
    };
    
    template<>
    class luaStack<std::string>{
      public:
      static std::string get(lua_State *L, int ia){
        return luaL_checkstring(L,ia);
      }
      static void push(lua_State *L, std::string s){
        lua_pushstring(L,s.c_str());
      }
      static std::string getName(){
        return "string";
      }
    };
    
    template <typename type>
    class luaStack<type *>{
      typedef struct { type *pT;} userdataType;
      public:
      static type* get(lua_State *L, int ia){
        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
        if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
        return ud->pT; 
      }
      static void push(lua_State *L,type *obj){
        userdataType *ud = static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType)));
        ud->pT=obj;
        luaL_getmetatable(L,className<type>::get().c_str());  // lookup metatable in Lua registry
        lua_setmetatable(L, -2);
      }
      static std::string getName(){
        return className<type>::get();
      }
    };
    template <typename type>
    class luaStack<const type *>{
      typedef struct { type *pT;} userdataType;
      public:
      static type* get(lua_State *L, int ia){
        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
        if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
        return ud->pT; 
      }
      static void push(lua_State *L,const type *obj){
        userdataType *ud = static_cast<userdataType*>(lua_newuserdata(L, sizeof(userdataType)));
        ud->pT=(type*)obj;
        luaL_getmetatable(L,className<type>::get().c_str());  // lookup metatable in Lua registry
        lua_setmetatable(L, -2);
      }
      static std::string getName(){
        return className<type>::get();
      }
    };
    
    template <typename type>
    class luaStack<type &>{
      typedef struct { type *pT;} userdataType;
      public:
      static type& get(lua_State *L, int ia){
        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
        if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
        return *ud->pT; 
      }
      static std::string getName(){
        return className<type>::get();
      }
    };
    
    template <typename type>
    class luaStack<const type &>{
      typedef struct { type *pT;} userdataType;
      public:
      static type& get(lua_State *L, int ia){
        userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
        if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
        return *ud->pT; 
      }
      static std::string getName(){
        return className<type>::get();
      }
    };
    
    //static
    template <typename cb>
    class argTypeNames;
    template <typename tr, typename t0, typename t1, typename t2, typename t3, typename t4, typename t5>
    class argTypeNames<tr (*)(t0,t1,t2,t3,t4,t5)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
        names.push_back(luaStack<t1>::getName());
        names.push_back(luaStack<t2>::getName());
        names.push_back(luaStack<t3>::getName());
        names.push_back(luaStack<t4>::getName());
        names.push_back(luaStack<t5>::getName());
      }
    };
    template <typename tr, typename t0, typename t1, typename t2, typename t3, typename t4>
    class argTypeNames<tr (*)(t0,t1,t2,t3,t4)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
        names.push_back(luaStack<t1>::getName());
        names.push_back(luaStack<t2>::getName());
        names.push_back(luaStack<t3>::getName());
        names.push_back(luaStack<t4>::getName());
      }
    };
    template <typename tr, typename t0, typename t1, typename t2, typename t3>
    class argTypeNames<tr (*)(t0,t1,t2,t3)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
        names.push_back(luaStack<t1>::getName());
        names.push_back(luaStack<t2>::getName());
        names.push_back(luaStack<t3>::getName());
      }
    };
    template <typename tr, typename t0, typename t1, typename t2>
    class argTypeNames<tr (*)(t0,t1,t2)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
        names.push_back(luaStack<t1>::getName());
        names.push_back(luaStack<t2>::getName());
      }
    };
    template <typename tr, typename t0, typename t1>
    class argTypeNames<tr (*)(t0,t1)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
        names.push_back(luaStack<t1>::getName());
      }
    };
    template <typename tr, typename t0>
    class argTypeNames<tr (*)(t0)>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
        names.push_back(luaStack<t0>::getName());
      }
    };
    template <typename tr>
    class argTypeNames<tr (*)()>{
      public:
      static void get(std::vector<std::string> &names){
        names.clear();
        names.push_back(luaStack<tr>::getName());
      }
    };
    
    template <typename cb>
    class argTypeNames;
    template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3, typename t4, typename t5>
    class argTypeNames<tr (tObj::*)(t0,t1,t2,t3,t4,t5)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0,t1,t2,t3,t4,t5)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3, typename t4>
    class argTypeNames<tr (tObj::*)(t0,t1,t2,t3,t4)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0,t1,t2,t3,t4)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3>
    class argTypeNames<tr (tObj::*)(t0,t1,t2,t3)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0,t1,t2,t3)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1, typename t2>
    class argTypeNames<tr (tObj::*)(t0,t1,t2)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0,t1,t2)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1>
    class argTypeNames<tr (tObj::*)(t0,t1)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0,t1)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0>
    class argTypeNames<tr (tObj::*)(t0)>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)(t0)>::get(names);
      }
    };
    template <typename tr, typename tObj>
    class argTypeNames<tr (tObj::*)()>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr(*)()>::get(names);
      }
    };
    
    
    // const 
    template <typename cb>
    class argTypeNames;
    template <typename tr, typename tObj, typename t0, typename t1, typename t2, typename t3>
    class argTypeNames<tr (tObj::*)(t0,t1,t2,t3)const>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr (*)(t0,t1,t2,t3)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1, typename t2>
    class argTypeNames<tr (tObj::*)(t0,t1,t2)const>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr (*)(t0,t1,t2)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0, typename t1>
    class argTypeNames<tr (tObj::*)(t0,t1)const>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr (*)(t0,t1)>::get(names);
      }
    };
    template <typename tr, typename tObj, typename t0>
    class argTypeNames<tr (tObj::*)(t0)const>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr (*)(t0)>::get(names);
      }
    };
    template <typename tr, typename tObj>
    class argTypeNames<tr (tObj::*)()const>{
      public:
      static void get(std::vector<std::string> &names){
        argTypeNames<tr (*)()>::get(names);
      }
    };
    
    /*** template to call c function from the lua stack ***/
    //static, return 
    template < typename tRet, typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L,tRet (*_f)(t0,t1,t2,t3)) {
      if (lua_gettop(L)==5)
        lua_remove(L,1);
      luaStack<tRet>::push(L,(*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3),luaStack<t3>::get(L,4)));
      return 1;
    };
    template < typename tRet, typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L,tRet (*_f)(t0,t1,t2)) {
      if (lua_gettop(L)==4)
        lua_remove(L,1);
      luaStack<tRet>::push(L,(*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3)));
      return 1;
    };
    template < typename tRet, typename t0, typename t1>
    static int luaCall(lua_State *L,tRet (*_f)(t0,t1)) {
      if (lua_gettop(L)==3)
        lua_remove(L,1);
      luaStack<tRet>::push(L,(*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2)));
      return 1;
    };
    template < typename tRet, typename t0>
    static int luaCall(lua_State *L,tRet (*_f)(t0)) {
      if (lua_gettop(L)==2)
        lua_remove(L,1);
      luaStack<tRet>::push(L,(*(_f))(luaStack<t0>::get(L,1)));
      return 1;
    };
    template < typename tRet>
    static int luaCall(lua_State *L,tRet (*_f)()) {
      printf("top=%i\n",lua_gettop(L));
      if (lua_gettop(L)==1)
        lua_remove(L,1);
      luaStack<tRet>::push(L,(*(_f))());
      return 1;
    };
    
    //static, no return 
    template < typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L, void (*_f)(t0,t1,t2,t3)) {
      if (lua_gettop(L)==5)
        lua_remove(L,1);
      (*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3),luaStack<t3>::get(L,4));
      return 1;
    };
    template <typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L, void (*_f)(t0,t1,t2)) {
      if (lua_gettop(L)==4)
        lua_remove(L,1);
     (*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3));
      return 1;
    };
    template <typename t0, typename t1>
    static int luaCall(lua_State *L,void (*_f)(t0,t1)) {
      if (lua_gettop(L)==3)
        lua_remove(L,1);
      (*(_f))(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2));
      return 1;
    };
    template <typename t0>
    static int luaCall(lua_State *L, void (*_f)(t0)) {
      if (lua_gettop(L)==2)
        lua_remove(L,1);
      (*(_f))(luaStack<t0>::get(L,1));
      return 1;
    };
    template < >
    int luaCall(lua_State *L,void (*_f)()) {
      if (lua_gettop(L)==1)
        lua_remove(L,1);
      (*(_f))();
      return 1;
    };
    
    //const, return
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2,t3) const) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2) const) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1) const) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0) const) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2)));
      return 1;
    };
    template <typename tObj, typename tRet>
    static int luaCall(lua_State *L,tRet (tObj::*_f)() const) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))());
      return 1;
    };
    
    //non const, return
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2, typename t3, typename t4, typename t5>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2,t3,t4,t5)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5),luaStack<t4>::get(L,6),luaStack<t5>::get(L,7)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2, typename t3, typename t4>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2,t3,t4)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5),luaStack<t4>::get(L,6)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2,t3)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1,t2)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0, typename t1>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0,t1)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3)));
      return 1;
    };
    template <typename tObj, typename tRet, typename t0>
    static int luaCall(lua_State *L,tRet (tObj::*_f)(t0)) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2)));
      return 1;
    };
    template <typename tObj, typename tRet>
    static int luaCall(lua_State *L,tRet (tObj::*_f)()) {
      luaStack<tRet>::push(L,(luaStack<tObj*>::get(L,1)->*(_f))());
      return 1;
    };
    
    //const, no return
    template <typename tObj, typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2,t3) const) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5));
      return 0;
    };
    template <typename tObj, typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2) const) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4));
      return 0;
    };
    template <typename tObj, typename t0, typename t1>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1) const) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3));
      return 0;
    };
    template <typename tObj, typename t0>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0) const) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2));
      return 0;
    };
    template <typename tObj>
    static int luaCall(lua_State *L,void (tObj::*_f)() const) {
      (luaStack<tObj*>::get(L,1)->*(_f))();
      return 0;
    };
    
    
    
    //non const, no return
    template <typename tObj, typename t0, typename t1, typename t2, typename t3, typename t4, typename t5>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2,t3,t4,t5)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5),luaStack<t4>::get(L,6),luaStack<t5>::get(L,7));
      return 1;
    };
    template <typename tObj, typename t0, typename t1, typename t2, typename t3, typename t4>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2,t3,t4)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5),luaStack<t4>::get(L,6));
      return 1;
    };
    template <typename tObj, typename t0, typename t1, typename t2, typename t3>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2,t3)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4),luaStack<t3>::get(L,5));
      return 0;
    };
    template <typename tObj, typename t0, typename t1, typename t2>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1,t2)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3),luaStack<t2>::get(L,4));
      return 0;
    };
    template <typename tObj, typename t0, typename t1>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0,t1)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2),luaStack<t1>::get(L,3));
      return 0;
    };
    template <typename tObj, typename t0>
    static int luaCall(lua_State *L,void (tObj::*_f)(t0)) {
      (luaStack<tObj*>::get(L,1)->*(_f))(luaStack<t0>::get(L,2));
      return 0;
    };
    template <typename tObj>
    static int luaCall(lua_State *L,void (tObj::*_f)()) {
      (luaStack<tObj*>::get(L,1)->*(_f))();
      return 0;
    };
    
    
    /*** arg names ***/
    
    
    /*** actual bindings classes ***/
    class luaMethodBinding :public methodBinding{
      public:
      std::string _luaname;
      virtual int call (lua_State *L)=0;
      luaMethodBinding(const std::string luaname){
        _luaname=luaname;
      }
      luaMethodBinding(){
        _luaname="";
      }
      virtual void getArgTypeNames(std::vector<std::string> &names){};
    };
    
    template <typename cb>
    class methodBindingT:public luaMethodBinding {
      public:
      cb _f;
      methodBindingT(const std::string luaname,cb f):luaMethodBinding(luaname) {
        _f=f;
      }
      int call (lua_State *L) {
        return luaCall(L,_f);
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<cb>::get(names);
      }
    };
    
    template <typename tObj, typename t0=void, typename t1=void , typename t2=void, typename t3=void>
    class constructorBindingT:public luaMethodBinding {
      public:
      int call (lua_State *L) {
        lua_remove(L,1);
        (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3), luaStack<t3>::get(L,4))));
        return 1;
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<void (tObj::*)(t0,t1,t2,t3)>::get(names);
      }
    };
    
    template <typename tObj>
    class constructorBindingT<tObj,void,void,void,void>:public luaMethodBinding {
      public:
      int call (lua_State *L) {
        lua_remove(L,1);
        (luaStack<tObj*>::push(L,new tObj()));
        return 1;
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<void (tObj::*)()>::get(names);
      }
    };
    template <typename tObj, typename t0>
    class constructorBindingT<tObj,t0,void,void,void>:public luaMethodBinding {
      public:
      int call (lua_State *L) {
        lua_remove(L,1);
        (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1))));
        return 1;
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<void (tObj::*)(t0)>::get(names);
      }
    };
    template <typename tObj, typename t0, typename t1>
    class constructorBindingT<tObj,t0,t1,void,void>:public luaMethodBinding {
      public:
      int call (lua_State *L) {
        lua_remove(L,1);
        (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2))));
        return 1;
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<void (tObj::*)(t0,t1)>::get(names);
      }
    };
    template <typename tObj, typename t0, typename t1, typename t2>
    class constructorBindingT<tObj,t0,t1,t2,void>:public luaMethodBinding {
      public:
      int call (lua_State *L) {
        lua_remove(L,1);
        (luaStack<tObj*>::push(L,new tObj(luaStack<t0>::get(L,1),luaStack<t1>::get(L,2),luaStack<t2>::get(L,3))));
        return 1;
      }
      void getArgTypeNames(std::vector<std::string> &names) {
        argTypeNames<void (tObj::*)(t0,t1,t2)>::get(names);
      }
    };
    
    class classBinding {
      std::string _className;
      binding *_b;
      luaMethodBinding *_constructor;
      static int callMethod(lua_State *L) {
        return  static_cast<luaMethodBinding*>(lua_touserdata(L, lua_upvalueindex(1)))->call(L); 
      }
      //I'd like to remove the "luaMethodBinding" and the "methodBindingT" classes and use this callback insteak
      //but for some reason I don't understand, it does not work
      static int callMethod2(lua_State *L) {
        int (*f)(lua_State*,void *)=(int (*)(lua_State*,void*))(lua_touserdata(L,lua_upvalueindex(1)));
        void *ff=lua_touserdata(L,lua_upvalueindex(2));
        return (*f)(L,ff);
      }
      static int tostring (lua_State *L) {
        typedef struct {void *pt;} userdata;
        char buff[32];
        const char *name = luaL_checkstring(L,lua_upvalueindex(1));
        userdata *ud = static_cast<userdata*>(lua_touserdata(L, 1));
        sprintf(buff, "%p", ud->pt);
        lua_pushfstring(L, "%s (%s)", name, buff);
        return 1;
      }
      void setConstructorLuaMethod(luaMethodBinding *constructor){
        lua_State *L = _b->L;
        lua_getglobal(L,_className.c_str());
        int methods = lua_gettop(L);
        lua_getmetatable(L,methods);
        int mt = lua_gettop(L);
        lua_pushlightuserdata(L,(void*)constructor);
        lua_pushcclosure(L, callMethod, 1);
        lua_setfield(L, mt,"__call");
        lua_pop(L,2);
        _constructor=constructor;
      }
      //for the doc
      std::string _description;
      classBinding *_parent;
    public:
      std::set<classBinding *> children;
      inline luaMethodBinding *getConstructor(){
        return _constructor;
      }
      // get userdata from Lua stack and return pointer to T object
      classBinding(binding *b, std::string name){
        _b=b;
        lua_State *L = _b->L;
        _className=name;
        _constructor=NULL;
        _parent=NULL;
    
        // there are 3 tables involved :
        // methods : the table of the C++ functions we bind (exept constructor)
        // metatable : the metatable attached to each intance of the class, falling back to method (metatable.__index=method)
        // mt : the metatable of method to store the constructor (__new) and possibly falling back to the parent metatable( __index)
        lua_newtable(L); // methods  
        int methods = lua_gettop(L);
        lua_pushvalue(L, methods);
        lua_setglobal(L, _className.c_str()); // global[_className] = methods
    
        luaL_newmetatable(L, _className.c_str());
        int metatable = lua_gettop(L);
    
        lua_pushvalue(L, methods);
        lua_setfield(L, metatable,"__index"); // metatable.__index=methods
    
        lua_pushstring(L,name.c_str());
        lua_pushcclosure(L, tostring,1);
        lua_setfield(L, metatable,"__tostring");
    
        lua_newtable(L);
        int mt = lua_gettop(L);
    
        lua_setmetatable(L, methods); // setmetatable(methods, mt)
        lua_pop(L, 2);  // drop metatable and method table
      } 
      template<typename parentType>
      void setParentClass(){
        if(_parent)
          Msg::Error("Multiple inheritance not implemented in lua bindings for class %s",_className.c_str());
        std::string parentClassName=className<parentType>::get();
        _parent = _b->classes[parentClassName];
        _parent->children.insert(this);
        lua_getglobal(_b->L,_className.c_str());
        lua_getmetatable(_b->L,-1);
        int mt=lua_gettop(_b->L);
        lua_getglobal(_b->L,parentClassName.c_str());
        lua_setfield(_b->L,mt,"__index");// mt.__index = global[_parentClassName] // this is the inheritance bit
        lua_pop(_b->L,2);
      }
    
      void setDescription(std::string description){
        _description = description;
      }
      inline const std::string getDescription()const {return _description;};
      inline classBinding *getParent()const {return _parent;};
      std::map<std::string, luaMethodBinding *> methods;
    
      template <typename cb>
      methodBinding *addMethod(std::string n, cb f){
        luaMethodBinding *mb = new methodBindingT<cb>(n,f);
        methods[n]=mb;
        lua_State *L=_b->L;
    
        lua_getglobal(L,_className.c_str());
        int methods=lua_gettop(L);
        /*int (*lc)(lua_State *,cb)=(int(*)(lua_State*,cb))luaCall;
        lua_pushlightuserdata(L, (void*)lc);
        lua_pushlightuserdata(L, (void*)f);
        lua_pushcclosure(L, callMethod2, 2);*/
        lua_pushlightuserdata(L, (void*)mb);
        lua_pushcclosure(L, callMethod, 1);
        lua_setfield(L,methods, n.c_str()); //className.name = callMethod(mb)
        lua_pop(L,1);
        return mb; 
      }
      template <typename tObj, typename t0, typename t1, typename t2, typename t3 >
      methodBinding *setConstructor(){
        luaMethodBinding *constructorLua = new constructorBindingT<tObj,t0,t1,t2,t3>;
        setConstructorLuaMethod(constructorLua);
        return constructorLua;
      }
      template <typename tObj, typename t0, typename t1, typename t2 >
      methodBinding *setConstructor(){
        luaMethodBinding *constructorLua = new constructorBindingT<tObj,t0,t1,t2>;
        setConstructorLuaMethod(constructorLua);
        return constructorLua;
      }
      template <typename tObj, typename t0, typename t1>
      methodBinding *setConstructor(){
        luaMethodBinding *constructorLua = new constructorBindingT<tObj,t0,t1>;
        setConstructorLuaMethod(constructorLua);
        return constructorLua;
      }
      template <typename tObj, typename t0>
      methodBinding *setConstructor(){
        luaMethodBinding *constructorLua = new constructorBindingT<tObj,t0>;
        setConstructorLuaMethod(constructorLua);
        return constructorLua;
      }
      template<typename tObj>
      methodBinding *setConstructor(){
        luaMethodBinding *constructorLua = new constructorBindingT<tObj>;
        setConstructorLuaMethod(constructorLua);
        return constructorLua;
      }
      inline const std::string getClassName()const {return _className;}
    };
    
    
    template<typename t>
    classBinding *binding::addClass(std::string name){
      className<t>::set(name);
      classBinding *cb=new classBinding(this,name);
      classes[name]=cb;
      return cb;
    }
    #endif
    #endif