lua-users home
lua-l archive

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

I have a C++ object that I want to access from Lua. So I made it a userdata by overriding the new operator like this:

Object::operator new(size_t size)
    lua_State* L = getGlobalState();
    void* ud = lua_newuserdata(L, size);
    return ud;

This leaves the userdata on the stack, so my Object ctor fiddles with it (gives it a common metatable and refs it so it doesn't get GC'ed). Then it gets popped.

This all works fine and I now have a userdata object which has my C++ instance data. The problem is, I can't push the C++ "this" pointer onto the Lua stack, at least not in any way that results in it looking like a userdata. The only thing I can do is:

    lua_pushlightuserdata(L, this);

and if I then call lua_gettable(), it will fail because you can't gettable on a lightuserdata. But you can do this on a userdata as long as its metatable has an __index function, which mine does.

What I need is something like:

   lua_pushuserdata(L, this);

But such a thing does not exist. I can understand why. You don't want to go pushing some random pointer and then expect Lua to try to access its metatable and then crash! To solve this, I created a global table called __objects, with weak values. The key to this table is the this pointer, as a lightuserdata, and the value is the userdata. Making the values weak will allow these objects to get collected even if they are in this table. So now I can simply do this:

    lua_pushstring(L, "__objects");
    lua_gettable(L, LUA_GLOBALSINDEX);
    lua_pushlightuserdata(L, this);

and voila' I have the userdata on the stack. The problem is this is very slow, requiring two table accesses and stack fiddling every time.

Am I missing something in the public API, or is there really no more efficient way to move between C++ and Lua?

chris marrin                ,""$,          b`    $                             ,,.
                        mP     b'                            , 1$'
        ,.`           ,b`    ,`                              :$$'
     ,|`             mP    ,`                                       ,mm
   ,b"              b"   ,`            ,mm      m$$    ,m         ,`P$$
  m$`             ,b`  .` ,mm        ,'|$P   ,|"1$`  ,b$P       ,`  :$1
 b$`             ,$: :,`` |$$      ,`   $$` ,|` ,$$,,`"$$     .`    :$|
b$|            _m$`,:`    :$1   ,`     ,$Pm|`    `    :$$,..;"'     |$:
P$b,      _;b$$b$1"       |$$ ,`      ,$$"             ``'          $$
 ```"```'"    `"`         `""`        ""`                          ,P`
"As a general rule,don't solve puzzles that open portals to Hell"'