lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hello...

Some Lua behaviour that has bothered me since I started using it was:

"It is not an error to access a non-initialized variable; you just get
the special value nil as the result"
http://www.lua.org/pil/1.2.html <http://www.lua.org/pil/1.2.html>

Sometimes, (in my case, ALL the time) this is not desirable behaviour.
For example, I was trying to figure out a sensible way to expose an
enum in C to Lua. For example,

enum Action
{
  Action_Stand
  Action_Walk,
  Action_Run,
};

So, I figured I'd make a table called Action and add a key for each
(integer) value in the enum. Problem is, if I do this in my script:

some_action       = Action.Stand
some_other_action = Action.Dance

Then some_action will be set to an integer and some_other_action will
be set to a nil... silently. Obviously, I'll notice this error when I
attempt to actually /use/ some_other_action, but it would be nice if
Lua would bail out with a warning straight away.

Well here's the solution.

Create a seperate table with its __index metamethod set to print a "no
such key" error message. I called this table "Object". Now, set this
table as the metatable of any enum tables. I found this useful
everywhere; "Object" is effectively my top-level base class.

And here it is implemented in C++:

extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

#include <string>
#include <iostream>

using namespace std;

//------------------------------------------------------------------------------
void newTable(lua_State* state, const string& table)
{
  lua_newtable(state);
  lua_setglobal(state, table.c_str());
}

//------------------------------------------------------------------------------
void setTableInt(lua_State*    state,
               const string& table,
               const string& key,
               int           integer)
{
  lua_getglobal(state, table.c_str());
  lua_pushstring(state, key.c_str());
  lua_pushnumber(state, integer);
  lua_settable(state, -3);
  lua_pop(state, 1);
}

//------------------------------------------------------------------------------
void setTableCFunction(lua_State*    state,
                     const string& table,
                     const string& key,
                     lua_CFunction function)
{
  lua_getglobal(state, table.c_str());
  lua_pushstring(state, key.c_str());
  lua_pushcfunction(state, function);
  lua_settable(state, -3);
  lua_pop(state, 1);
}

//------------------------------------------------------------------------------
void setMetaTable(lua_State*    state,
                const string& table,
                const string& metatable)
{
  lua_getglobal(state, table.c_str());
  lua_getglobal(state, metatable.c_str());
  lua_setmetatable(state, -2);
  lua_pop(state, 1);
}

//------------------------------------------------------------------------------
int index(lua_State* state)
{
  string key(luaL_checkstring(state, 2));

  string error = "No such key \"" + key + "\"";
  luaL_error(state, error.c_str());
}

//------------------------------------------------------------------------------
enum Action
{
  Action_Stand,
  Action_Walk,
  Action_Run
};

//------------------------------------------------------------------------------
int main(int argc, char** argv)
{
  const char* script = argv[1];
  lua_State*  state  = lua_open();

  luaL_openlibs(state);

  newTable(state, "Object");
  setTableCFunction(state, "Object", "__index", index);

  newTable(state, "Action");
  setMetaTable(state, "Action", "Object");
  setTableInt(state, "Action", "Stand", Action_Stand);
  setTableInt(state, "Action", "Walk",  Action_Walk);
  setTableInt(state, "Action", "Run",   Action_Run);

  if (luaL_loadfile(state, script) == 0)
  {
      int errors = lua_pcall(state, 0, LUA_MULTRET, 0);

      if (errors)
      {
          cerr << lua_tostring(state, -1) << endl;
          return -1;
      }
  }

  lua_close(state);

  return 0;
}

--------------------------------------------------------------------------------

When I type to execute the line:

a = Action.JumpAroundLikeACrazyPerson

I get the error:

script.lua:1: No such key "JumpAroundLikeACrazyPerson"

Enjoy.

Matt Comi

http://members.iinet.net.au/~mattcomi/mt/bigbucket/ <http://members.iinet.net.au/%7Emattcomi/mt/bigbucket/>
--
This email is confidential and intended solely for the use of the individual to whom it is addressed. Any views or opinions presented are solely those of the author and do not necessarily represent those of NAUTRONIX LTD.

If you are not the intended recipient, you have received this email in error and use, dissemination, forwarding, printing, or copying of this email is strictly prohibited. If you have received this email in error please contact the sender.
Although our computer systems use active virus protection software, and we take various measures to reduce the risk of viruses being transmitted in e-mail messages and attachments sent from this company, we cannot guarantee that such e-mail messages and attachments are free from viruses on receipt.  It is a condition of our using e-mail to correspond with you, that any and all liability on our part arising directly or indirectly out of any virus is excluded.  Please ensure that you run virus checking software on all e-mail messages and attachments before reading them.