title: Lua, C++, and poor man's subclassing
body: <p>I'm lead dev for <a href="http://bitfighter.org" rel="noreferrer">Bitfighter</a>, and we're working with a mix of Lua and C++, using Lunar (a variant of Luna, available <a href="http://lua-users.org/wiki/CppBindingWithLunar" rel="noreferrer">here</a>) to bind them together.  </p>
  
  <p>I know this environment does not have good support for object orientation and inheritance, but I'd like to find some way to at least partially work around these limitations.</p>
  
  <p>Here's what I have:</p>
  
  <p><b>C++ Class Structure</b><br></p>
  
  <pre>
      GameItem
         |---- Rock
         |---- Stone
         |---- RockyStone
  
      Robot
  </pre>
  
  <p>Robot implements a method called <i>getFiringSolution(GameItem item)</i> that looks at the position and speed of <i>item</i>, and returns the angle at which the robot would need to fire to hit <i>item</i>.</p>
  
  <pre><code>-- This is in Lua
  angle = robot:getFiringSolution(rock)
  if(angle != nil) then
      robot:fire(angle)
  end
  </code></pre>
  
  <p>So my problem is that I want to pass <i>rocks</i>, <i>stones</i>, or <i>rockyStones</i> to the getFiringSolution method, and I'm not sure how to do it.</p>
  
  <p>This works for Rocks only:</p>
  
  <pre><code>// C++ code
  S32 Robot::getFiringSolution(lua_State *L) 
  {
     Rock *target = Lunar&lt;Rock&gt;::check(L, 1);
     return returnFloat(L, getFireAngle(target));    // returnFloat() is my func
  }
  </code></pre>
  
  <p>Ideally, what I want to do is something like this:</p>
  
  <pre><code>// This is C++, doesn't work
  S32 Robot::getFiringSolution(lua_State *L) 
  {
     GameItem *target = Lunar&lt;GameItem&gt;::check(L, 1);
     return returnFloat(L, getFireAngle(target));    
  }
  </code></pre>
  
  <p>This potential solution does not work because Lunar's check function wants the object on the stack to have a className that matches that defined for GameItem.  (For each object type you register with Lunar, you provide a name in the form of a string which Lunar uses to ensure that objects are of the correct type.)</p>
  
  <p>I would settle for something like this, where I have to check every possible subclass:</p>
  
  <pre><code>// Also C++, also doesn't work
  S32 Robot::getFiringSolution(lua_State *L) 
  {
     GameItem *target = Lunar&lt;Rock&gt;::check(L, 1);
     if(!target)
         target = Lunar&lt;Stone&gt;::check(L, 1);
     if(!target)
         target = Lunar&lt;RockyStone&gt;::check(L, 1);
  
     return returnFloat(L, getFireAngle(target));    
  }
  </code></pre>
  
  <p>The problem with this solution is that the check function generates an error if the item on the stack is not of the correct type, and, I believe, removes the object of interest from the stack so I only have one attempt to grab it.</p>
  
  <p>I'm thinking I need to get a pointer to the Rock/Stone/RockyStone object from the stack, figure out what type it is, then cast it to the correct thing before working with it.</p>
  
  <p>The key bit of Lunar which does the type checking is this:</p>
  
  <pre><code>// from Lunar.h
  // get userdata from Lua stack and return pointer to T object
  static T *check(lua_State *L, int narg) {
    userdataType *ud =
      static_cast&lt;userdataType*&gt;(luaL_checkudata(L, narg, T::className));
    if(!ud) luaL_typerror(L, narg, T::className);
    return ud-&gt;pT;  // pointer to T object
  }
  </code></pre>
  
  <p>If I call it thusly:</p>
  
  <pre><code>GameItem *target = Lunar&lt;Rock&gt;::check(L, 1);
  </code></pre>
  
  <p>then the luaL_checkudata() checks to see if the item on the stack is a Rock.  If so, everything is peachy, and it returns a pointer to my Rock object, which gets passed back to the getFiringSolution() method.  If there is a non-Rock item on the stack, the cast returns null, and luaL_typerror() gets called, which sends the app off into lala land (where the error handling prints a diagnostic and terminates the robot with extreme prejudice).</p>
  
  <p>Any ideas on how to move forward with this?</p>
  
  <p>Many thanks!!</p>
  
  <p><b>Best solution I've come up with... ugly, but works</b></p>
  
  <p>Based on the suggestions below, I came up with this:</p>
  
  <pre><code>template &lt;class T&gt;
  T *checkItem(lua_State *L)
  {
     luaL_getmetatable(L, T::className);
     if(lua_rawequal(L, -1, -2))         // Lua object on stack is of class &lt;T&gt;
     {
        lua_pop(L, 2);                   // Remove both metatables
        return Lunar&lt;T&gt;::check(L, 1);    // Return our object
     }
     else                                // Object on stack is something else
     {
        lua_pop(L, 1);    // Remove &lt;T&gt;'s metatable, leave the other in place 
                          // for further comparison
        return NULL;
     }
  }
  </code></pre>
  
  <p>Then, later...</p>
  
  <pre><code>S32 Robot::getFiringSolution(lua_State *L)
  {
     GameItem *target;
  
     lua_getmetatable(L, 1);    // Get metatable for first item on the stack
  
     target = checkItem&lt;Rock&gt;(L);
  
     if(!target)
        target = checkItem&lt;Stone&gt;(L);
  
     if(!target)
        target = checkItem&lt;RockyStone&gt;(L);
  
     if(!target)    // Ultimately failed to figure out what this object is.
     {
        lua_pop(L, 1);                      // Clean up
        luaL_typerror(L, 1, "GameItem");    // Raise an error
        return returnNil(L);                // Return nil, but I don't think this 
                                            // statement will ever get run
     }
  
     return returnFloat(L, getFireAngle(target));    
  }
  </code></pre>
  
  <p>There are probably further optimizations I can do with this... I'd really like to figure out how to collapse this into a loop because, in reality, I will have a lot more than three classes to deal with, and this process is a bit cumbersome.</p>
  
  <p><b>Slight improvement on the above solution</b></p>
  
  <p>C++:</p>
  
  <pre><code>GameItem *LuaObject::getItem(lua_State *L, S32 index, U32 type)
  {
    switch(type)
    {
      case RockType:
          return Lunar&lt;Rock&gt;::check(L, index);
      case StoneType:
          return Lunar&lt;Stone&gt;::check(L, index);
      case RockyStoneType:
          return Lunar&lt;RockyStone&gt;::check(L, index);
      default:
          displayError();
     }
  }
  </code></pre>
  
  <p>Then, later...</p>
  
  <pre><code>S32 Robot::getFiringSolution(lua_State *L)
  {
     S32 type = getInteger(L, 1);                 // My fn to pop int from stack
     GameItem *target = getItem(L, 2, type);
  
     return returnFloat(L, getFireAngle(target)); // My fn to push float to stack  
  }
  </code></pre>
  
  <p>Lua helper function, included as a separate file to avoid user needing to add this manually to their code:</p>
  
  <pre><code>function getFiringSolution( item )
    type = item:getClassID()      -- Returns an integer id unique to each class
    if( type == nil ) then
       return nil
     end
    return bot:getFiringSolution( type, item )
  end 
  </code></pre>
  
  <p>User calls this way from Lua:</p>
  
  <pre><code>   angle = getFiringSolution( item )
  </code></pre>