lua-users home
lua-l archive

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

It was thus said that the Great 云风 Cloud Wu once stated:
> Lua is a embedded language, it uses powerful userdata to wrap the c object
> as the lua object. But sometimes it's not enough.
> For example, if we have a C struct like this :
> struct foo {
>   struct foo1 foo1;
>   struct foo2 *foo2;
> };
> We can use userdata to store struct foo in lua variables :
> struct foo * f = lua_newuserdata(L, sizeof(*f));
> How to reference sub struct foo1/foo2 in lua ? maybe we can give the
> userdata a metatable, implementing an __index metamethod.
> But foo.foo1 or foo.foo2 should be a new userdata. It needs more complex
> and expensive way :
> Creating a proxy userdata to access a part of struct foo, put the reference
> of proxy userdata in uservalue of userdata foo to prevent collecting foo
> before foo1/foo2 proxy, etc.

  No.  Just create two userdatas, one of struct foo1 and one for struct
foo2.  struct foo can then be converted to a plain Lua table with two
fields, foo1 and foo2, both using the appropriate custom user data.

  Or, convert both struct foo1 and struct foo2 to full Lua tables with more
primitive types.  I do this *all the time* for stuff at work.  In one
instance, it's a binary file containing around 100,000,000 records.  The
file itself is mmap()ed into memory and wrapped up into a userdata type. 
The fields themselves aren't complicated and the index method just creates a
Lua table with a string and bunch of booleans (stored internally as a 32-bit
value).  Another instance is a binary file of around 44k in size that is
broken down into primitive Lua types (numbers, strings, tables, etc) when
read.  Yeah, it's quite a bit of code (going to and from Lua) but once done,
it's done, and performance hasn't been an issue.

> So I suggest introduce a new mechanism of userdata to simplify them. I call
> it userdata slice (maybe it's not a good name).
> If we can associate an integer to the userdata value, the userdata whould
> be more flexible. It is different from uservalue, because uservalue is in
> userdata object, not in value.
> An userdata object has only one uservalue , but each userdata value can has
> an unique associated integer.
> Two C API needed:
> int lua_getuserslice(lua_State *L, int index);
> void lua_setuserslice(lua_State *L, int index, int slice);
> Any value with type LUA_TUSERDATA in lua is an two 32bit integer tuple ( or
> two 16bit integer for small lua), one is the userdata (32bit int) handle ,
> another is the associated integer.
> Using handle instead of really address of userdata object because we can
> put two 32bit integer in 64bit lua value.



  I remember this crap going from 16 bit to 32 bit systems [1] and frankly,
I'd rather not have to live through that again going to 64 bit [3][4].

  Also, I don't think I'm following your API there.  I have this structure:

	typedef union sockaddr_all
	  struct sockaddr     sa;  
	  struct sockaddr_in  sin;
	  struct sockaddr_in6 sin6;
	  struct sockaddr_un  ssun;
	} sockaddr_all__t;

which I'm using for a userdata.  I have a custom __index method associated
with this that gives me the following "fields":

	addr		- text representation of IPv4/IPv6 address
	daddr		- other text representation of IPv4/IPv6 address [5]
	addrbits	- The raw binary bits that make up an IPv4/IPv6 address
	port		- port number
	family		- string, either 'ip', 'ip6' or 'unix'.
	display		- textual representation of address and port.

  How would your system with with that?


[1]	Want to know how false this is?  I can name a mainstream system that
	used C, that could have both 16 *AND* 32 bit pointers *IN THE SAME
	PROGRAM* and where ints were 16 *BITS* long. [2]

[2]	Ever wonder what FAR means in zlib.h? [6] Yeah, it comes from that
	time frame.  Never want to go back to it.

[3]	One my my pet peeves with LuaJIT is the 2G limit on memory
	allocation, because of tricks played with pointers.

[4]	I have an old program written in the early 90s that I'm having a
	hell of a time porting to 64 bit systems because of the assumption
	that an integer and pointers are all 32 bits and are completely

[5]	The difference between the two only show up for IPv6 addresses.  The
	addr field will return "fc00::1" while the daddr field will return

[6]	Are you SURE you want to ask?  Because I can and will answer that.