lua-users home
lua-l archive

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


  Thank you, I've got things working now.  Here's my working implementation
in case you experts see something that can be optimized.  I'm currently
storing the pointer to the C struct as the only element in the table.

void PushVertex(lua_State *pL, Vertex *pVert) {
	lua_newtable(pL);
	int table=lua_gettop(pL);
	lua_pushstring(pL, "__cpointer");	//Table only has one element - a pointer
to our C struct
	lua_pushlightuserdata(pL, pVert);
	lua_settable(pL, table);

	lua_newtable(pL);
	int metatable=lua_gettop(pL);
	lua_pushstring(pL, "__index");
	lua_pushcfunction(pL, vertex_read);
	lua_settable(pL, metatable);

	lua_pushstring(pL, "__newindex");
	lua_pushcfunction(pL, vertex_assign);
	lua_settable(pL, metatable);
	lua_setmetatable(pL, table);
}

static int vertex_assign (lua_State *L) {
	//Retrieve key
	const char *c=lua_tostring(L, -2);

	//Retrieve pointer to our struct
	lua_pushstring(L, "__cpointer");
	lua_gettable(L, -4);
	Vertex *pVert = (Vertex *)lua_touserdata(L, -1);
	lua_pop(L, 1);

	if (c[0] && !c[1]) {
		if (c[0]=='x') {
			int n=lua_tonumber(L, -1);
			pVert->x=n;
		} else if (c[0]=='y') {
			int n=lua_tonumber(L, -1);
			pVert->y=n;
		} else if (c[0]=='z') {
			int n=lua_tonumber(L, -1);
			pVert->z=n;
		}
	}
	//Pop the table, value and key
	lua_pop(L, 3);

	return 0;
}

static int vertex_read (lua_State *L) {
	//Retrieve key
	const char *c=lua_tostring(L, -1);
	lua_pop(L, 1);

	//Retrieve pointer to our struct
	lua_pushstring(L, "__cpointer");
	lua_gettable(L, -2);
	Vertex *pVert = (Vertex *)lua_touserdata(L, -1);
	lua_pop(L, 1);

	int n=lua_type(L, -1);
	if (c[0] && !c[1]) {
		if (c[0]=='x')
			lua_pushnumber(L, pVert->x);
		else if (c[0]=='y')
			lua_pushnumber(L, pVert->y);
		else if (c[0]=='z')
			lua_pushnumber(L, pVert->z);
		else
			return 0;
	} else
		return 0;
	return 1;
}


-----Original Message-----
From: lua-bounces@bazar2.conectiva.com.br
[mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of Virgil Smith
Sent: Monday, June 14, 2004 11:52 AM
To: 'Lua list'
Subject: RE: __assign


You have to use __newindex for assignments and __index for reads.

Furthermore, if you want to catch accesses to already "existing" entries you
have to use 2 tables.  One can contain whatever assigned values you wish to
keep, and the other remains empty so that its __newindex and __index methods
continue to be called.  Of course the __newindex and __index methods will
have to access the table that actually holds the previously assigned values.


-----Original Message-----
From: lua-bounces@bazar2.conectiva.com.br
[mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of Dan East
Sent: Monday, June 14, 2004 9:22 AM
To: Lua list
Subject: RE: __assign


  I'm afraid I don't have anything in print regarding Lua.

  Thanks for the suggestion - this sort of works.  I did a quick test, and
my __newindex handler is called when a non-existent element is assigned a
value, but not when it is read:

  x=MyClass.x	--Does not trigger __newindex handler
  MyClass.x=10	--Triggers __newindex handler

  So how is reading values handled in the proxy table?

  So at this point I can catch writes, or let the user read, but not both at
once.  :)

  Dan East


-----Original Message-----
From: lua-bounces@bazar2.conectiva.com.br
[mailto:lua-bounces@bazar2.conectiva.com.br]On Behalf Of Aaron Brown
Sent: Monday, June 14, 2004 11:02 AM
To: Lua list
Subject: Re: __assign


Dan East wrote:

>   Is there some non-trivial implementation issue that
> prevents an __assign metatable event within Lua?  Or is
> there some other mechanism already providing the same
> functionality?

It can currently be done with __newindex and a proxy table.
I don't see this explained in the wiki anywhere, but it is
on page 115 of Programming in Lua, if you have it.

Briefly, the idea is that the table the user assigns to is
always empty -- its __newindex metamethod does any
housekeeping you want done on every assignment, plus the
actual assignment to the real table (which the user never
directly accesses).

--
Aaron