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 Dirk Laurie once stated:
> The Four Laws of a userdata:
> 
> 1. The closest a full userdata ever gets to your C code is the Lua stack.
> 2. You can create a new userdata on the stack.
> 3. You can receive an old userdata on the stack.
> 4. There is no other way to return a userdata to Lua.
> 
> You can check the registry type of a userdata on the stack, get its
> block address, modify its contents, push the block address as a light
> userdata — but you can't transform that light userdata back into a
> full one.  Once it's off the stack, it is gone.
> 
> Right?

  I'm not so sure ...

typedef int foo__t;	/* doesn't really matter */

int foo(lua_State *L)
{
  foo__t *pfoo;

  pfoo = lua_newuserdata(L,1);
  luaL_getmetatable(L,FOO_TYPE);
  lua_setmetatable(L,-2);
  return 1;
}

int foo_full_to_light(lua_Stack *L)
{
  foo__t *pfooa;
  foo__t *pfoob;

  pfooa = luaL_checkudata(L,1,FOO_TYPE);
  pfoob = malloc(sizeof(foo__t));
  memcpy(pfoob,pfooa,sizeof(foo__t));
  lua_pushlightuserdata(L,pfoob);
  return 1;
}

int foo_ligh_to_full(lua_Stack *L)
{
  foo__t *pfooa;
  foo__t *pfoob;

  if (!lua_islightuserdata(L,1))
    return luaL_error(L,"not a light user data");

  pfooa = lua_touserdata(L,1);
  pfoob = lua_newuserdata(L,sizeof(foo__t));
  memcpy(pfoob,pfooa,sizeof(foo__t));
  free(pfooa);
  luaL_getmetatable(L,FOO_TYPE);
  lua_setmetatable(L,-2);
  return 1;
}

struct luaL_Reg foo_reg[] =
{
  { "foo"	        , foo               } ,
  { "foo_to_light"	, foo_full_to_light } ,
  { "foo_to_full"	, foo_light_to_full } ,
  { NULL		, NULL              }
};

int luaopen_foo(lua_State *L)
{
  luaL_register(L,"foo",foo_reg);
  return 1;
}

--------------[ Lua code ]---------------------

foo = require "foo"

x = foo.foo()
y = foo.foo_to_light(x) -- dup x (full user data) to y (light user data)
x = nil			-- remove x
z = foo.foo_to_full(y)	-- dup y (light user data) to z (full user data)

------------[ end of line ]----------------------

  Is there something I'm missing?

  -spc (other than this being for Lua 5.1 ... )