lua-users home
lua-l archive

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


On Aug 7, 2005, at 9:07:28, Rici Lake wrote:
On 6-Aug-05, at 8:23 PM, Uli Kusterer wrote:
for i=100,1,-1 do
    aRoom = Room.new()
    print( tostring( aRoom ) )
    aRoom = nil
end

Any particular reason you didn't choose to write:

for i = 100, 1, -1 do
  local aRoom = Room.new()
  print(tostring(aRoom))
end

-- or even
for i = 1, 100 do print(tostring(Room.new())) end
-- ;)

First and foremost, I originally just tried the part inside the loop. When that didn't call the destructor, I thought maybe there's a threshold for the GC how many objects have to be there to be considered worth collecting, so I put it a loop around it. I also wanted to have some room for trying out some member functions later. I didn't use the second because I simply didn't consider it readable enough.

Leaving that aside, Room.new() must contain the following:

  RoomData *self = lua_pushuserdata(L, sizeof(RoomData));
  luaL_getmetatable(L, "PACEmaker.Room");
  lua_setmetatable(L, -2);

Thanks, this is exactly what I'm doing in UKAdventureNewRoom(), the difference being I'm using UKRoom* instead of UserData.

If you don't have this code, or something that looks like it, that's why it's not working. If you're using a lightuserdata rather than a pushuserdata, that is why it's not working (light user data don't have metatable).

 I'm using full metadata.

If none of the above is the reason, try checking the return values from luaL_getmetatable and lua_setmetatable, and perhaps you'll get a hint.

 Will do.

Since you mention c++ constructors, there are two common ways of dealing with the RoomData object.

The "simplest" (or at least most common) is to simply use a pointer to the actual object; the statement after self = lua_pushuserdata (...) would be *self = new Room; and RoomData would either be typedef'd or replace with Room*, depending on your style preferences.

 Yes, that's what I'm trying to do.

The more elegant way, which works as long as you're ok with letting Lua manage your memory for you, is to use "placement new" syntax, in which case the self = statement would look something like this:

Room self = new(lua_pushuserdata(L, sizeof(Room)) Room(...);

One of the nice things about placement-new is that the __gc method will typically simply be an explicit call to the class destructor; furthermore, it can be omitted completely under a specific but not uncommon case, where no member variable of the class needs to be destructed. The placement expression can be supplied by a template function if you're careful; I think there is an example on the Lua Wiki.

That's the first time I hear of this approach. I simply did what the docs (the Programming with Lua book) suggested, assuming that this was the recommended technique, and the one most tested and thus most likely to work without much work. I'll look into this some more.

Cheers,
-- M. Uli Kusterer
http://www.zathras.de