views:

630

answers:

1

Hi!

Can anyone pls tell me that how to use lua_pop() function correctly in C++.

  • Should I call it when I use a lua_get*() function ? like.

    lua_getglobal(L, "something");

    lua_pop(L, 1);

or how to use it ? Will the garbage collector clear those stuff after the threshold ? Thanks.

+7  A: 

You call lua_pop() to remove items from the Lua stack. For simple functions, this can be entirely unnecessary since the core will clean up the stack as part of handling the return values.

For more complex functions, and especially for C code that is calling into Lua, you will often need to pop things from the stack to prevent the stack from growing indefinitely.

The lua_getglobal() function adds one item to the stack when called, which is either nil if the global doesn't exist or the value of the named global variable. Having a copy of that value on the stack protects it from the garbage collector as long as it is there. That value needs to remain on the stack as long as it is in use by the C code that retrieved it, because if the global were modified, the copy on the stack might be the only remaining reference.

So the general patterns for using a global are something like these:

void doMyEvent(lua_State *L) {
    lua_getglobal(L, "MyEvent");
    lua_call(L, 0, 0);  /* pops the function and 0 parameters, pushes 0 results */
}

double getGlobalDouble(lua_State *L, const char *name) {
    double d;
    lua_getglobal(L,name);
    d = lua_tonumber(L,1); /* extracts the value, leaves stack unchanged */
    lua_pop(L,1);          /* pop the value to leave stack balanced */
    return d;
}

char *copyGlobalString(lua_State *L, const char *name) {
    char *s = NULL;
    lua_getglobal(L,name);
    if (!lua_isnil(L,-1))
        s = strdup(lua_tostring(L,-1));
    lua_pop(L,1);
    return s;
}

In the last example, I am careful to copy the content of the string because the pointer returned by lua_tostring() is only guaranteed to be valid as long as the value remains on the stack. The requires that a caller of copyGlobalString() is responsible for calling free() later.

Note too that recent editions of the Lua manual include a notation along with each function that identifies the number of stack entries consumed, and the number pushed. This helps avoid unexpected stack growth.

RBerteig
+1, Lua's comment style in C++ code? :-)
Nick D
@nick... facepalm! Its better now ;-)
RBerteig
Hey! Thanks for the help. And one more question, What is the difference between calling lua_call(L, 0, 0); and lua_pop(L,1); for remove the FUNCTIONS ?? I mean why did you use lua_call(L, 0, 0) rather than using lua_pop(L,1) ?
Morpheus
I assumed that the likely reason to retrieve a function value was to actually call the function, which is what `lua_call(L,0,0)` does in the example. The function value is called with no parameters (the first zero) and its return is adjusted to no values (the second zero). In production code you might prefer `lua_pcall()` which catches any thrown errors from the Lua side.
RBerteig
@RBerteig Can I ask another question ? After calling a lua function from C/C++ who is responsible for removing return values ? is it C++ ? Thanks.
Morpheus
The C side is responsible for handling the number of return values it requested from the Lua side. In my sample here, I asked for no return values, so there's nothing to clean up. If I wanted one value, I would have to pop it or otherwise consume it so that the stack doesn't grow without bound.
RBerteig