lua-users home
lua-l archive

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

> is there any chance to get tag methods for reading
> and assigning from/to userdata/usertypes?

You could use toLua to do this.  However, this didn't suit my needs
(too much overhead -- the data is accessed mostly from C++, and I didn't
want to be asking Lua for the data all the time) so I'm writing
my own C++ framework (called, unimaginatively "luapp") for exporting
objects to Lua.  The thing that my framework handles that most of the
other Lua/C++ frameworks do not is the case where you have classes
which want to export member objects which themselves are Lua objects:

class Point2d {
    double x, y;

class Rect2d {
    Point2d p1, p2;

With my framework you can do (Lua) stuff like:

    r = Rect2d{ p1 = Point{ x=10, y=20 }, p2 = Point{ x=30, y=40 } }

as well as:

    r.p1 = Point{ x=1, y=2 }

(actually, I generally write my constructors for 'simple' objects like
'point's and 'color's and 'rect's so that they take a () style constructor:  
p = Point(10,20) since nearly everyone knows that means: p = Point{x=10,y=20},
but for more complex objects, the named construction is pretty spiffy ;-)

... and it doesn't lose any of the objects ..

If you roll your own, watch out for this:

    Rect2d r;


    // assumes that 'this' has been pulled from Lua stack arg 1 already ..
    // by a 'thunk' function which handles the gettable() tag method callback
    Rect2d::gettable(lua_State *L)
	const char *fld = luaL_check_string(L,2);

	if (strcmp(fld,"p1")==0) {
	    lua_newuserdatabox(L,&p1,Point::tag);	// XXX -- danger!
	} ...

Watch out for the line marked XXX -- it seems like the obvious thing
to do, but if you have a GC function for the 'Point' tag, it wil be
called with the address of p1 -- WHICH IS INSIDE another object...

My framework 'knows' (well, you tell it ;-) about 'member' objects
and will not free them when they go out of scope.

Another gotcha is that potentially the object which holds 'p1' in
this case could be GC'ed before the object returned by 'p1'.  This
would case the pointer inside of the userdata to become 'wild'.
My framework handles this by holding a locked reference on the
'parent' object until all member objects have been gc'ed.

(This stuff is hard-won knowledge .. the interaction of userdata
and GC is not very clearly documented, and the semantics of user
data objects changes from 4.0 to 4.1 ;-)

The framework keeps track of it's objects with a C++ STL::map<>,
and is pretty quick.  Once I get a real application behind it, I'll
start doing some real benchmarking (it may be faster to keep them
in a sorted STL::vector<> instead of a STL::map<>).

If anyone is interested in my framework, I'll clean it up and post
it on my Lua page.  

Mike Cuddy (, MC312), Programmer, Daddy, Human.
Fen's Ende Software, Redwood City, CA, USA, Earth, Sol System, Milky Way.

       Now I lay me down to sleep / CVS, I pray, my code to keep.  
       If disks crash before I wake: / format, newfs, cvs up, make.

       Join CAUCE: The Coalition Against Unsolicited Commercial E-mail.