lua-users home
lua-l archive

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


Doug Rogers wrote:
Shea Martin wrote:

Sorry to be dense, but I am still not following.
lua_pushstring( vm, "Event:log" );
lua_pushcclosure( vm, l_event_log, 0 );
lua_settable( vm, -3 );
lua_pushstring( vm, "Event:name" );
lua_pushstring( vm, eventname );
lua_settable( vm, -3 );

The code above is the same as saying

mt["Event:log"] = l_event_log
mt["Event:name"] = event_name

Note that luaL_newmetatable() places the table's name in the registry,
not in the global table, so 'mt' above is really just the anonymous
table that's left on the top of the stack.

These are understandable newbie mistakes. Just (re)read the sections of
PiL that contain C examples - chapters 25 and 26 in particular. Also,
you may want to (re)read the section on methods (the ':' syntactical
sugar), chapter 16. Note that ':' only works for function calls.

What you really want is a function with key "log", and a string with key
"name" to hold the name field. I suspect that what you *really* want is
the 'name' field to be present in an instance of an event, not in the
class (table "Event" plus its metatable).

// Untested...
// Create global table to hold "Event".
lua_newtable( vm);

// Create metatable.
luaL_newmetatable( vm, "Event.mt");
lua_pushstring( vm, "log" );
lua_pushcclosure( vm, l_event_log, 0 );  // Need a closure?
lua_settable( vm, -3 );

lua_pushvalue( vm, -2);    // Get copy of table Event to top.
lua_setfield( vm, -2, "__index");  // mt.__index = Event

lua_setmetatable( vm, -2);  // Attach metatable.

lua_pushcfunction( vm, l_event_new);  // Sample below.
lua_setfield( vm, -2, "new");
lua_setglobal( vm, "Event");   // Put main table in module.

Most likely you will also need some sort of mechanism for creating
objects of that type. I called that 'new' above. In that function you
will use luaL_getmetatable() to retrieve the metatable by name from the
registry, then you'll attach that to a new table, possibly like this
(untested):

int l_event_new(lua_State* L, const char* event_name)
{
  lua_newtable(L);                    // local obj = {}
  luaL_getmetatable(L, "Event.mt");   // setmetatable(obj, mt)
  lua_setmetatable(L, -2);
  lua_pushstring(L, event_name);     // obj.name = event_name
  lua_settable(L, -2, "name");
  return 1;                           // return obj
}

-- In Lua:
ev = Event.new('attack')
ev:log()

Those are some untested hints. You may want to invest the time (it's not
too long) to understand what is happening in the Lua-only version of
this, then see how it is implemented using the C API. It may be that
'log' should be a global function rather than an object method.

Good luck!

Doug


I want to pass an Event object to a function called 'start', which is defined in the script. I used your example for defining Event. Instead of registereing l_event_new, I just create the new table on the stack, and do a pcall( vm, 1, 1, 0 ). It seems that everything works except my member function 'log'. Index 'log' is nil, ie, not defined.



void DefinePlayerEvent( lua_State* vm )
{	
	lua_newtable( vm );

	lua_pushstring( vm, "log" );
	lua_pushcclosure( vm, l_event_log, 0 );
	lua_settable( vm, -3 );

	lua_pushvalue( vm, -2 );  //get Event from global space
	lua_setfield( vm, -2, "__index" ); // mt.__index = Event

	lua_setmetatable( vm, -2 ); //attach metatable

	//lua_setglobal( vm, "Event" );
}

void PutPlayerEventOnLuaStack( lua_State* vm, const char* eventname, int player_id, float x, float y )
{
	lua_newtable( vm );
	luaL_getmetatable( vm, "Event.mt" );
	lua_setmetatable( vm, -2 );

	
	lua_pushinteger( vm, player_id );
	lua_setfield( vm, -2, "player_id" );

	lua_pushnumber( vm, x );
	lua_setfield( vm, -2, "x" );
	
	lua_pushnumber( vm, y );
	lua_setfield( vm, -2, "y" );

	lua_pushstring( vm, eventname );
	lua_setfield( vm, -2, "name" );
}

Still reading, not sure what I am missing here.

~S