Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 203177
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 11, 20262026-05-11T17:21:20+00:00 2026-05-11T17:21:20+00:00

I’m lead dev for Bitfighter , and we’re working with a mix of Lua

  • 0

I’m lead dev for Bitfighter, and we’re working with a mix of Lua and C++, using Lunar (a variant of Luna, available here) to bind them together.

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.

Here’s what I have:

C++ Class Structure

    GameItem
       |---- Rock
       |---- Stone
       |---- RockyStone

    Robot

Robot implements a method called getFiringSolution(GameItem item) that looks at the position and speed of item, and returns the angle at which the robot would need to fire to hit item.

-- This is in Lua
angle = robot:getFiringSolution(rock)
if(angle != nil) then
    robot:fire(angle)
end

So my problem is that I want to pass rocks, stones, or rockyStones to the getFiringSolution method, and I’m not sure how to do it.

This works for Rocks only:

// C++ code
S32 Robot::getFiringSolution(lua_State *L) 
{
   Rock *target = Lunar<Rock>::check(L, 1);
   return returnFloat(L, getFireAngle(target));    // returnFloat() is my func
}

Ideally, what I want to do is something like this:

// This is C++, doesn't work
S32 Robot::getFiringSolution(lua_State *L) 
{
   GameItem *target = Lunar<GameItem>::check(L, 1);
   return returnFloat(L, getFireAngle(target));    
}

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.)

I would settle for something like this, where I have to check every possible subclass:

// Also C++, also doesn't work
S32 Robot::getFiringSolution(lua_State *L) 
{
   GameItem *target = Lunar<Rock>::check(L, 1);
   if(!target)
       target = Lunar<Stone>::check(L, 1);
   if(!target)
       target = Lunar<RockyStone>::check(L, 1);

   return returnFloat(L, getFireAngle(target));    
}

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.

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.

The key bit of Lunar which does the type checking is this:

// 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<userdataType*>(luaL_checkudata(L, narg, T::className));
  if(!ud) luaL_typerror(L, narg, T::className);
  return ud->pT;  // pointer to T object
}

If I call it thusly:

GameItem *target = Lunar<Rock>::check(L, 1);

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).

Any ideas on how to move forward with this?

Many thanks!!

Best solution I’ve come up with… ugly, but works

Based on the suggestions below, I came up with this:

template <class T>
T *checkItem(lua_State *L)
{
   luaL_getmetatable(L, T::className);
   if(lua_rawequal(L, -1, -2))         // Lua object on stack is of class <T>
   {
      lua_pop(L, 2);                   // Remove both metatables
      return Lunar<T>::check(L, 1);    // Return our object
   }
   else                                // Object on stack is something else
   {
      lua_pop(L, 1);    // Remove <T>'s metatable, leave the other in place 
                        // for further comparison
      return NULL;
   }
}

Then, later…

S32 Robot::getFiringSolution(lua_State *L)
{
   GameItem *target;

   lua_getmetatable(L, 1);    // Get metatable for first item on the stack

   target = checkItem<Rock>(L);

   if(!target)
      target = checkItem<Stone>(L);

   if(!target)
      target = checkItem<RockyStone>(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));    
}

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.

Slight improvement on the above solution

C++:

GameItem *LuaObject::getItem(lua_State *L, S32 index, U32 type)
{
  switch(type)
  {
    case RockType:
        return Lunar<Rock>::check(L, index);
    case StoneType:
        return Lunar<Stone>::check(L, index);
    case RockyStoneType:
        return Lunar<RockyStone>::check(L, index);
    default:
        displayError();
   }
}

Then, later…

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  
}

Lua helper function, included as a separate file to avoid user needing to add this manually to their 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 

User calls this way from Lua:

   angle = getFiringSolution( item )
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-11T17:21:20+00:00Added an answer on May 11, 2026 at 5:21 pm

    You should tell us what exactly does not work in your code. I suppose that it is Lunar<Rock>::check(L, 1) that fails for all non-Rocks. Am I correct?

    Also it would be fine if you specified which version of Lunar you use (a link to it would be great).

    If it is this one, then class type is stored in the Lua object metatable (one may say that this metatable is the type).

    Looks like the simplest way to check if object is a Rock without patching Lunar is to call luaL_getmetatable(L, Rock::className) to get class metatable and to compare it with lua_getmetatable(L, 1) of your first argument (note luaL in the first function name). This is a bit hackish, but should work.

    If you fine with patching Lunar, one of possible ways is to add some __lunarClassName field to the metatable and store T::name there. Provide lunar_typename() C++ function (outside of the Lunar template class — as we do not need T there) then, and return from it the value of that __lunarClassName field of argument’s metatable. (Do not forget to check if object has metatable and that metatable has such field.) You may check Lua object type by calling lunar_typename() then.

    A bit of advice from personal experience: the more of business logic you push to Lua, the better. Unless you’re pressed by severe performance constraints, you probably should consider to move all that hierarchy to Lua — your life would become much simpler.

    If I may help you further, please say so.

    Update: The solution you’ve updated your post with, looks correct.

    To do the metatable-based dispatch in C, you may use, for example, a map of integral lua_topointer() value of the luaL_getmetatable() for a type to a function object/pointer which knows how to deal with that type.

    But, again, I suggest to move this part to Lua instead. For example: Export type-specific functions getFiringSolutionForRock(), getFiringSolutionForStone() and getFiringSolutionForRockyStone() from C++ to Lua. In Lua, store table of methods by metatable:

    dispatch =
    {
      [Rock] = Robot.getFiringSolutionForRock;
      [Stone] = Robot.getFiringSolutionForStone;
      [RockyStone] = Robot.getFiringSolutionForRockyStone;
    }
    

    If I’m right, the next line should call the correct specialized method of robot object.

    dispatch[getmetatable(rock)](robot, rock)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 97k
  • Answers 97k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer In general it's not simple to do what you're asking,… May 11, 2026 at 7:19 pm
  • Editorial Team
    Editorial Team added an answer Are you absolutely committed to still using Trace? If not,… May 11, 2026 at 7:19 pm
  • Editorial Team
    Editorial Team added an answer You can use this script: IF EXISTS (SELECT * FROM… May 11, 2026 at 7:19 pm

Related Questions

I ran into a problem. Wrote the following code snippet: teksti = teksti.Trim() teksti
I am currently running into a problem where an element is coming back from
Seemingly simple, but I cannot find anything relevant on the web. What is the
Configuring TinyMCE to allow for tags, based on a customer requirement. My config is
Is it possible to replace javascript w/ HTML if JavaScript is not enabled on

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.