lua-users home
lua-l archive

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


Hi Daniel, hi all,

the approach that I mentioned in my initial post actually works!

I just set the metatable of the "a" table to the same metatable that was originally only intended to be used with the userdata. That is, the metatable of "a" and the metatable of "a.userdata" are the same, namely the one that was originally only intended for the userdata as described in chapter 28.3.

Daniel Collins wrote:
The approach I took to extending the functionality of userdata with lua
code is quite simple, but not totally transparent. I just aggregate the
userdata into a table. This is similar to the approach you mention,
except I didn't try to make it work like inheritance via metatables
since I cant see how it can work.

Sounds like our approaches are very similar, but I did not explicitly think about inheritance issues so far...

-- create a userdata object
local ud = system.createUD()

-- create the enclosing table
local wrapper = { userdata = ud }
setmetatable(wrapper, getmetatable(ud))

Yes, looks very much like my approach, too, except for the fact that I do all this in the C++ code.

-- Now, if ud has a method "methodOne", the following call succeeds
since methodOne is found in the metatable of wrapper
wrapper:methodOne()

Yes!   :-)

but the first parameter to the C function that implements methodOne is
not the userdata, but the table. So the function fails.

Well, I just rewrote my C functions to expect the "a" or "wrapper" table as the first argument, and then look up the userdata field in this table in order to get what used to be in the first argument of the C function.

It would work for userdata functions that don't expect the userdata as
the first parameter, but that is not the usual situation. The only way I
can get the above code to work is with:

wrapper.methodOne(wrapper.userdata)

Which defeats the entire purpose of setting the userdata metatable into
the table in the first place.

See above - just look up the userdata field in the C function.

I am still a Lua newb though, so there may well be tried and tested ways
of extending userdata with additional lua functions. If there are, then
I am really interested in using them.

The only other problem that I encountered with the approach outlined so far was that I had trouble with calling the "a:OnMouseClick()" or "wrapper:someMethod()" functions from C code, because

    lua_getglobal(LuaState, "a");
    // if (!lua_istable(LuaState, -1)) ...
    lua_pushstring(LuaState, "OnMouseEnter");
    lua_gettable(LuaState, -2);

yielded a message saying "PANIC: unprotected error in call to Lua API (loop in gettable)" and my program was hard aborted. I don't understand exactly why it loops (infinite recursion related to metatables?) here, but using lua_rawget() instead of lua_gettable() solved the problem.

(If somebody knows why lua_rawget() works while lua_gettable() doesn't, please let me know!)

Best regards,
Carsten



--
Ca3D - Engine    http://www.Ca3D-Engine.de
Carsten Fuchs    http://www.Ca3D-Engine.de/c_Carsten.php