[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: R: Re: How to export associative arrays to an embedded lua script?
- From: Sean Conner <sean@...>
- Date: Mon, 12 Oct 2015 16:23:43 -0400
It was thus said that the Great linuxfan@tin.it once stated:
>
> >storing the lua value for my just created tables, and they work as
>
> >expected. Dirk said that this is not a good idea, because lua doesn't
>
> >assure the pointer stays valid, perhaps after a garbage collection
>
>
> First of all, sorry - I don't understand how to post correctly under a
> given topic. It's easy to start a topic, not so easy to post a message
> and make it go under the correct thread.
Are you reading this as email or through a website? Because email clients
offset a "respond" option that should keep the post in the current thread.
> Second, sorry again - I don't
> want to be pedantic, but someone could explain me better than the
> manual?
> Here: http://www.lua.org/manual/5.2/manual.html#4.5the lua manual says
> that a host application can store data in the registry, and also says
> that "you should use as key a string containing your library name, ...,
> or any Lua object created by your code". What I understand is that "lua
> objects created by your code" means "created by the host application".
> If so, this implies that it is safe to take the lua value for an object
> (say, "its pointer"), and use it in whatever manner because that value
> will never change (as long as the object exists, of course). If such a
> value is good to be used as a key in the registry, it is also good to
> be used as a key in the host application. or not?
Here's a simple example. It's in C, not Pascal, but it does illustrate
one way of handling your problem. This is for a single structure (record)
but can be expanded to any number.
/*--------------------------------------------------------------------
; a name to tag our metatable for this data structure. It's not
; really needed for this example, but I'm using it anyway to provide
; some addtional typechecking and in case we have any other
; functions that might want to typecheck the metatable.
;--------------------------------------------------------------------*/
#define TYPE_FOO "typefoo"
/*---------------------------------------------------------------
; The format of the structure (record) we want to mirror to Lua.
;---------------------------------------------------------------*/
struct foo
{
char *lang;
int screenwidth;
}
/*------------------------------------------------------------------
; The metatable for this structure. We can index into it (__index)
; or set some fields (__newindex).
;------------------------------------------------------------------*/
luaL_Reg foo_meta[] =
{
{ "__index" , foometa___index },
{ "__newindex" , foometa___newindex },
{ NULL , NULL }
};
/*----------------------------------------------------------------
; pass our structure to Lua. For this example, I'm assuming the
; structure exists outside of Lua so we need to point to it. We
; define a pointer-to-a-pointer so we can point to our pre-existing
; structure. Lua will manage the lifetime of the
; pointer-to-pointer, but not of the structure itself.
;
; But first, we create our metatable for this structure and register
; it with Lua. Then we create our pointer-to-pointer, point to the
; pre-existing structure, then associate the metatable with this
; userdata
;------------------------------------------------------------------*/
int luaopen_foo(lua_State *L)
{
struct foo **rfoo;
luaL_newmetatable(L,TYPE_FOO);
luaL_setfuncs(L,foo_meta,0);
rfoo = lua_newuserdata(L,sizeof(rfoo));
*rfoo = global_real_foo;
luaL_getmetatable(L,TYPE_FOO);
lua_setmetatable(L,-2);
return 1;
}
/*-----------------------------------------------------------------
; The __index() metamethod. This expects our userdata and a key
; (and for this example, we are only using strings as keys). We
; check the key and return the appropriate value from our
; pre-existing structure. The line:
;
; struct foo *pfoo = *(struct foo **)luaL_checkudata(L,1,TYPE_FOO);
;
; Does two things---it makes sure we were passed the proper userdata
; (luaL_checkudata()) and it dereferences the pointer-to-pointer to
; point to the actual pre-exsiting structure we want to read.
;
; The rest should be stright forward code.
;-------------------------------------------------------------------*/
int foometa___index(lua_State *L)
{
struct foo *pfoo = *(struct foo **)luaL_checkudata(L,1,TYPE_FOO);
const char *name = luaL_checkstring(L,2);
if (strcmp(name,"lang") == 0)
lua_pushstring(L,pfoo->lang);
else if (strcmp(name,"screenwidth") == 0)
lua_pushinteger(L,pfoo->screenwidth);
return 1;
}
/*-----------------------------------------------------------------
; The __newindex() metamethod. This expects our userdata, a key and
; a value. The preamble (getting the userdata and key) is the same
; as above, only here instead of returning a field, we set it to a
; new value. The only caveat is that as written, we leak memory if
; we keep setting the lang field. We should really free (or
; overwrite---it depends upon the implementation) the field. But
; again, this is example code.
;-----------------------------------------------------------------*/
int foometa___newindex(lua_State *L)
{
struct foo *pfoo = *(struct foo**)luaL_checkudata(L,1,TYPE_FOO);
const char *name = luaL_checkstring(L,2);
if (strcmp(name,"lang") == 0)
pfoo->lang = strdup(luaL_checkstring(L,3));
else if (strcmp(name,"screenwidth") == 0)
pfoo->screenwidth = luaL_checkinteger(L,3);
return 0;
}
-spc