lua-users home
lua-l archive

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


On Mar 6, 2014, at 8:29 PM, Fabio Carneiro <vizouk@gmail.com> wrote:

> Hi, i don't understand Upvalues very well and i'm trying to create a function that returns a string and has 2 upvalues, could someone give me a example of function that when debugged shows nups (number of upvalues) equal 2?
> 
> 
> 
> static int teststring (lua_State *L) {
> 	int n = lua_gettop(L);
> 	std::str = "test"
> 	static int val;
> 	const char *cstr = str.c_str();
> 	lua_pushstring(L, cstr);
> 	return 1; 
> }
> 
> Now when i debug that function i want it to have 2 upvalues so i should use 
> 
>  lua_pushcclosure(L, &anotherfunc, 1);   ? I didn't quite understood this

Some pointers that you might find useful:

To use upvalues from C you need to create a C closure, which is an instance that combines a Lua-callable C function and one or more upvalues. This closure, when called from Lua, can then access these upvalues as private Lua values.

Assume the function that is to have upvalues is this:

int upfunc(lua_State *L) {
	…
}

To make this function into a closure that includes upvalues, you need to use lua_pushcclosure(). First, you push one or more values on the Lua stack that will be the upvalues. The values are pushed in “up value order”, that is the first pushed will be the first upvalue etc. For example, to have the two upvalues, an integer and a boolean, use this:

lua_pushinteger(L, 1);
lua_pushboolean(L, FALSE);
lua_pushcclosure(L, upfunc, 2);

This code will take the supplied C function (upfunc), pop the two upvalues off the stack, then push onto the stack a Lua closure. This Lua closure, which is a normal Lua callable function (LUA_TFUNCTION), can now be called from Lua like an other Lua function (using lua_call), stored in a variable etc etc.

When that new closure is called, the “upfunc” C function will be called by Lua. Now for the upvalue “magic”. In addition to being able to access the normal Lua stack in the C function, the C function has access to additional pseudo-indices that give it access to the upvalues. You access these indices using the lua_upvalueindex(n) macro. For example, here is how the C function would print the current value of the first (integer) upvalue and return the second (boolean) upvalue:

int upfunc(lua_State *L) {
	int x = lua_tointeger(L, lua_upvalueindex(1));	// Get 1st upvalue
	printf(“%d\n”, x);
	lua_pushvalue(L, lua_upvalueindex(2));	// Push 2nd upvalue onto stack
	return 1;	// .. and return it
}

Of course, just like with Lua functions, you can create additional closures from the same C function, each with different upvalues, each time you call lua_pushcclosure().

HTH

—Tim