tags:

views:

52

answers:

2

I'm learning how to bind C++ objects to Lua with type checking from the book Programming Gems 6 (Chapter 4.2). For the type checking the userdata/string pairs are being stored in an environment table, with the code given how to do that:

void Binder::pushusertype(void* udata, const char* tname) {
 lua_pushlightuserdata(L, udata); // push address 
 lua_pushvalue(L, -1);    // duplicate address
 lua_pushstring(L, tname);  // push type name
 lua_rawset(L, LUA_ENVIRONMENTINDEX); // envtable[address] = tname
}

Where the Binder class has a Lua State as an attribute, named "L"

As you can see the address is pushed twice. As this small piece of code is only given as an example it doesn't seem like a duplicate address pushed onto the stack would serve any purpose outside of this function, which leads me to believe there's a specific reason for it. So my question is, why would one do this?

+2  A: 

You don't.

The lua_rawset will pop tname & the duplicate off the stack, but will leave the original userdata on the stack. I'm not sure if its a typo (looks unlikely), I guess it might be needed later. Don't know if there is some more in the book, that mentions this, but thats what the code will do.

Mark Gossage
+1  A: 

This function does two things:

it pushes a lightuserdata object to the stack and it will be at lua stack position -1 when the function returns. It also updates the current function environment with the name tname stored at table key address (equal to udata). If the current function environment is the normal global environment, the equivalent Lua code would be:

local x = <udata as lightuserdata>
_G[x] = <tname>

One duplicate of x is used to do the _G[x] = ... thing, the other is left on the stack when the function returns (consistent with the name of the function that starts with push).

kaizer.se