[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: Userdata Environments
- From: "Jerome Vuarand" <jerome.vuarand@...>
- Date: Tue, 13 Feb 2007 19:42:20 -0500
Wesley Smith wrote:
> Do you have an URL of this?
> http://lua-users.org/wiki/UserdataEnvironmentExamples turns up an
> empty page.
>
> wes
Here is a freshly written complete and tested example, feel free to put
it on the wiki:
/*** module.c *****************************************************/
#include <lua.h>
#include <lauxlib.h>
#include <stdio.h>
#define FOO "foo"
static int lua__foo__do_it(lua_State* L)
{
printf("it's done in C\n");
return 0;
}
luaL_Reg foo_methods[] = {
{"do_it", lua__foo__do_it},
{0, 0},
};
static int lua__new(lua_State* L)
{
/* Create a new userdata */
lua_newuserdata(L, sizeof(int));
/* Set common metatable to that userdata */
lua_getfield(L, LUA_REGISTRYINDEX, FOO);
lua_setmetatable(L, -2);
/* Set a specific environment table to that userdata */
lua_newtable(L);
lua_setfenv(L, -2);
return 1;
}
luaL_Reg module_functions[] = {
{"new", lua__new},
{0, 0},
};
/* __index(self/U, key) */
static int lua__foo___index(lua_State* L)
{
int U = *(int*)lua_touserdata(L, 1);
if (lua_isnil(L, 2))
{
luaL_typerror(L, 2, "non-nil key");
}
/* Retrieve environment variable */
lua_getfenv(L, 1);
/* Check if that key points to something in environment */
lua_pushvalue(L, 2);
lua_gettable(L, -2);
if (!lua_isnil(L, -1))
{
return 1;
}
/* Pop environment and nil */
lua_pop(L, 2);
/* Fallback: Retrieve methods in metatable */
lua_getmetatable(L, 1);
lua_getfield(L, -1, "methods");
/* Look for key in methods */
lua_pushvalue(L, 2);
lua_gettable(L, -2);
/* Simply return it, even if its nil */
return 1;
}
static int lua__foo___newindex(lua_State* L)
{
int U = *(int*)lua_touserdata(L, 1);
if (lua_isnil(L, 2))
{
luaL_typerror(L, 2, "non-nil key");
}
/* Make sure we have a value in slot 3 */
if (lua_gettop(L)==2)
lua_pushnil(L);
/* Retrieve environment variable */
lua_getfenv(L, 1);
/* Set the value in the environment table */
lua_pushvalue(L, 2); /* Push key */
lua_pushvalue(L, 3); /* Push value */
lua_settable(L, -3); /* Assign */
return 0;
}
int luaopen_module(lua_State* L)
{
/* Create the metatable */
luaL_newmetatable(L, FOO);
/* Put userdata methods in metatable.methods */
lua_newtable(L);
luaL_register(L, 0, foo_methods);
lua_setfield(L, -2, "methods");
/* Set a __index metamethods that accesses environment table and
* fallback to metatable.methods */
lua_pushcfunction(L, lua__foo___index);
lua_setfield(L, -2, "__index");
/* Set a __newindex metamethods that put everything in the
* environment */
lua_pushcfunction(L, lua__foo___newindex);
lua_setfield(L, -2, "__newindex");
/* Create the module */
lua_newtable(L);
luaL_register(L, 0, module_functions);
return 1;
}
/******************************************************************/
---- test.lua ------------------------------------------------------
local module = require 'module'
local U = module.new()
U:do_it()
U.do_it = function() print("it's done in Lua") end
U:do_it()
--------------------------------------------------------------------
It should output:
it's done in C
it's done in Lua
Feel free to ask for more comments.