5

This is almost a duplicate of this question; however, the answer suggested there doesn't fix my problem, and I'm not using the luaL_dostring() macro directly (though I am using the same pair of calls that it expands to). Given this program:

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <lua.hpp>

static int _foo(lua_State* L)
{
    lua_pushinteger(L, 1);
    lua_pushinteger(L, 2);
    lua_pushinteger(L, 3);
    printf("In foo(): pushed %d elements...\n", lua_gettop(L));
    return 3;
}

int main()
{
    lua_State* L = luaL_newstate();
    luaL_openlibs(L);
    lua_pushcfunction(L, _foo);
    lua_setglobal(L, "foo");

    // This leaves three results on the stack...
    lua_pushcfunction(L, _foo);
    lua_pcall(L, 0, LUA_MULTRET, 0);
    int nresults = lua_gettop(L);
    printf("After foo(): %d results left on the stack...\n", nresults);
    lua_settop(L, 0);

    // ... and so does this.
    luaL_loadstring(L, "foo()");
    lua_pcall(L, 0, 3, 0);
    nresults = lua_gettop(L);
    printf("After foo(): %d results left on the stack...\n", nresults);
    lua_settop(L, 0);

    // But this does NOT. Why?
    luaL_loadstring(L, "foo()");
    lua_pcall(L, 0, LUA_MULTRET, 0);
    nresults = lua_gettop(L);
    printf("After foo(): %d results left on the stack...\n", nresults);
    return 0;
}

Why does the last call to lua_pcall(L, 0, LUA_MULTRET, 0) not leave any results on the stack? The output from running the above program is:

In foo(): pushed 3 elements...
After foo(): 3 results left on the stack...
In foo(): pushed 3 elements...
After foo(): 3 results left on the stack...
In foo(): pushed 3 elements...
After foo(): 0 results left on the stack...

I'm using Lua 5.1.5...

Community
  • 1
  • 1
evadeflow
  • 4,704
  • 38
  • 51

1 Answers1

6

In the first call you are pushing the C function foo onto the stack then calling it. But luaL_loadstring creates a chunk so in the 2nd and 3rd calls you are pushing a chunk then calling it, but the chunk does not return anything, the chunk just calls foo(). Hence

lua_pcall(L, 0, 3, 0);

creates 3 nils on the Lua stack because Lua makes sure that the 3 values you asked are there, even if chunk returned none. Also

lua_pcall(L, 0, LUA_MULTRET, 0);

returns nothing because the chunk returned nothing.

If you want to execute foo from Lua, put the foo global variable on the stack:

lua_getglobal(L, "foo");
lua_pcall(L, 0, LUA_MULTRET, 0);

Alternately, make the chunk return what foo() returns:

luaL_loadstring(L, "return foo()");
lua_pcall(L, 0, LUA_MULTRET, 0);
Oliver
  • 27,510
  • 9
  • 72
  • 103
  • 2
    Thanks @Scholli, that helped me figure out a solution to my particular problem, so I'm marking this answer as correct. I'm trying to make a debug console (actually, I'm just using socat to write to a Unix domain socket that the host app is listening on). The strings I'm receiving in the host app look sorta like ``foo.bar.get_property("baz", false)``, so it's a little inconvenient to push the function on the stack _by name_. But prepending "return " to the string in the ``luaL_loadstring()`` call works great. (I've got an edit in the queue to add this to your answer...) – evadeflow Dec 29 '13 at 20:47
  • Thanks, according to the SO policies, accepting it is the right thing to do (http://stackoverflow.com/help/accepted-answer). Regarding the edit you made to my answer, it is better to post a comment and let the author of an answer decide what to do. This is why the SO moderators rejected your edit. Edits of others' posts are meant to be used when it is such a small change that it is faster to do it yourself than to explain what needs fixing. The info you provide in your comment makes it clear enough that I should edit my answer (so I just did that). – Oliver Dec 30 '13 at 01:48