From a2ac13faf1c4d16e040c8ec65d39de697a90f54e Mon Sep 17 00:00:00 2001
From: Jonathan Lambrechts <jonathan.lambrechts@uclouvain.be>
Date: Mon, 3 May 2010 09:45:35 +0000
Subject: [PATCH] dynamic type-checking for binded functions

---
 Common/LuaBindings.cpp | 20 ++++++++++++++++++++
 Common/LuaBindings.h   |  9 +++++----
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/Common/LuaBindings.cpp b/Common/LuaBindings.cpp
index 4f1ae0e16a..d768a613e0 100644
--- a/Common/LuaBindings.cpp
+++ b/Common/LuaBindings.cpp
@@ -398,4 +398,24 @@ binding::~binding()
   }
 }
 
+void *binding::checkudata_with_inheritance (lua_State *L, int ud, const char *tname) {
+  void *p = lua_touserdata(L, ud);
+  if (!p)
+    return NULL;
+
+  lua_getglobal(L, tname);
+  if (ud<0) ud--;
+  int depth = 1;
+  while (luaL_getmetafield (L, ud, "__index")) {
+    depth ++;
+    if (lua_rawequal(L,-1, -depth) ) {
+      lua_pop(L, depth);
+      return p;
+    }
+    ud = -1;
+  }
+  lua_pop(L, depth);
+  return NULL;
+}
+
 #endif
diff --git a/Common/LuaBindings.h b/Common/LuaBindings.h
index ef8ba46eb8..14b74d885d 100644
--- a/Common/LuaBindings.h
+++ b/Common/LuaBindings.h
@@ -62,6 +62,7 @@ class binding {
   static binding *_instance;
   void checkDocCompleteness();
  public:
+  static void *checkudata_with_inheritance (lua_State *L, int ud, const char *tname);
   inline static binding *instance(){ return _instance ? _instance : new binding(); }
   lua_State *L;
   int readFile(const char *filename);
@@ -200,7 +201,7 @@ class luaStack<type *>{
   public:
   static type* get(lua_State *L, int ia)
   {
-    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
+    userdataType *ud=static_cast<userdataType*>(binding::checkudata_with_inheritance (L, ia, getName().c_str()));
     if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
     return ud->pT;
   }
@@ -225,7 +226,7 @@ class luaStack<const type *>{
   public:
   static type* get(lua_State *L, int ia)
   {
-    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
+    userdataType *ud=static_cast<userdataType*>(binding::checkudata_with_inheritance (L, ia, getName().c_str()));
     if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
     return ud->pT;
   }
@@ -250,7 +251,7 @@ class luaStack<type &>{
  public:
   static type& get(lua_State *L, int ia)
   {
-    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
+    userdataType *ud=static_cast<userdataType*>(binding::checkudata_with_inheritance (L, ia, getName().c_str()));
     if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
     return *ud->pT; 
   }
@@ -266,7 +267,7 @@ class luaStack<const type &>{
  public:
   static type& get(lua_State *L, int ia)
   {
-    userdataType *ud = static_cast<userdataType*>(lua_touserdata(L, ia));
+    userdataType *ud=static_cast<userdataType*>(binding::checkudata_with_inheritance (L, ia, getName().c_str()));
     if(!ud) luaL_typerror(L, ia, className<type>::get().c_str());
     return *ud->pT; 
   }
-- 
GitLab