2

i'm trying to create a function that has 2 upvalues when inspected from lua. debug.getinfo(fvalues).nups should be 2 .

static int fvalues (lua_State *L) {
    int n = lua_gettop(L);
    if (str.size() == 0) {
        str = "This_is_a_test";
    }
    const char *cstr = str.c_str();
    lua_pushstring(L, cstr);
    lua_pushcclosure(L, &fvalues, 1);
    lua_pushstring(L, cstr);
    lua_pushcclosure(L, &fvalues, 2);
    lua_pushstring(L, cstr);
    return 1; 
}

Shouldn't pushclosure create an upvalue in this case, i didn't understand well how this is supposed to work.

2 Answers 2

7

Is not very clear what you're trying to do. If you want to push C-closure fvalues with 2 upvalues, then:

int
main(int argc, char *argv[])
{
    ...
    lua_pushstring(L, "Hello, World!");
    lua_pushnumber(L, 3.14);
    lua_pushcclosure(L, fvalues, 2);
    lua_setglobal(L, "fvalues");
    ...
}

static int
fvalues(lua_State *L)
{
    printf("%s\n", lua_tostring(L, lua_upvalueindex(1)); // Hello, World!
    printf("%g\n", lua_tonumber(L, lua_upvalueindex(2)); // 3.14
    return 0;
}

Closure is created by passing lua_CFunction and values at top of the stack to lua_pushcclosure. Body of that function has nothing to do with creation of upvalues, it only can use them via lua_upvalueindex(n).

Sign up to request clarification or add additional context in comments.

Comments

3

The pattern is something like:

int fvalues (lua_State *L) {
    ... get function arguments with lua_to* functions ...
    ... get upvalues with lua_getupvalue and lua_upvalueindex and lua_to* functions ...
    ... use arguments and upvalues ...
}

int callFValues(lua_State *L) {
    const char* cstr = "This_is_a_test";
    // push two values that will be upvalues of fvalues
    lua_pushstring(L, cstr);
    lua_pushstring(L, cstr);
    // create closure using the two upvalues:
    lua_pushcclosure(L, &fvalues, 2);
    // call it: 
    lua_pcall(L, 0,0,0);
    return 1; 
}

Then register callFValues. If you want to return a closure (as is common in Lua script), for use by your Lua script, pretty much same:

int createClosure(lua_State *L) {
    const char* cstr = "This_is_a_test";
    // push two values that will be upvalues of fvalues
    lua_pushstring(L, cstr);
    lua_pushstring(L, cstr);
    // create closure using the two upvalues:
    lua_pushcclosure(L, &fvalues, 2);
    return 1; // return it to caller
}

Then register createClosure, call it from script as fval = createClosure() then fval is a closure of fvalues with the two upvalues created by createClosure.

Read section 27.3.3 of PIL for detailed example. But in your code, your fvalues, which is a lua_CFunction you want to close and call, is itself creating a closure of itself, this makes my head spin :) Also,

lua_pushstring(L, cstr);
lua_pushcclosure(L, &fvalues, 1);
lua_pushstring(L, cstr);
lua_pushcclosure(L, &fvalues, 2);

creates a closure for fvalues with the first string added to stack being its one unique upvalue; this removes the string from stack, and puts closure on stack; then you push another string, and create another closure of fvalues, this time with 2 upvalues: the first upvalue is the first closure created, the second one is the second string added. My head spins even more. Hopefully with the PIL section and the pattern I show you have clearer picture.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.