Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Steve Litt
Hi all,

I think I discovered a possible improvement to the documentation in the Lua
5.1 Reference Manual's description of lua_call() regarding calling of a
specific function in a Lua script.

http://www.lua.org/manual/5.1/manual.html#lua_call

For a newbie (me, for instance), I don't think this documentation is clear
enough about what you use for the nargs argument to lua_call() and therefore
lua_pcall. At one point it says:

"Finally you call lua_call; nargs is the number of arguments that you pushed
onto the stack."

While this is technically correct, the newbie might interpret this as the
number of arguments taken by the Lua function. It isn't. It's that number of
arguments plus one more that's used by the function name.

So if you interpret nargs as the number of args required by the Lua function
and do this:

    lua_getglobal(L, "tellme");
    if (lua_pcall(L, 0, 0, 0))
        bail(L, "lua_pcall() failed");

You get this at runtime:
=================
slitt@mydesk:~$ ./callfunc
In C, calling Lua

FATAL ERROR:
  lua_pcall() failed: attempt to call a nil value

slitt@mydesk:~$
=================

Only if you read VERY carefully and concentrate on the documentation's saying
"All arguments and the function value are popped from the stack when the
function is called" do you get the idea that maybe nargs includes the pushed
function name as well as the args required by the Lua function. In that case
you do this:

    lua_getglobal(L, "tellme");
    if (lua_pcall(L, 1, 0, 0))
        bail(L, "lua_pcall() failed");

And succeed:
=================
slitt@mydesk:~$ ./callfunc
In C, calling Lua
This is coming from lua.tellme.
Back in C again
slitt@mydesk:~$
=================

My suggestion is that just to help newbies, a strongly worded sentence be
added to the lua_call() doc in the manual saying that IF you push a function
name, that adds to nargs, and for instance, if the Lua function takes no
arguments but you push the function name via lua_getglobal() or something
similar, nargs is 1, not 0.

By the way, this C interface is entirely too cool. I love it. And I'm not
sure, but I think there may be an interface to Lazarus or Free Pascal, which
would solve A LOT of problems for me.

Thanks

SteveT

Steve Litt
Recession Relief Package
http://www.recession-relief.US
Twitter: http://www.twitter.com/stevelitt


Reply | Threaded
Open this post in threaded view
|

Re: Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Michal Kottman
On Thu, 2011-01-20 at 08:23 -0500, Steve Litt wrote:

> Hi all,
>
> I think I discovered a possible improvement to the documentation in the Lua
> 5.1 Reference Manual's description of lua_call() regarding calling of a
> specific function in a Lua script.
>
> http://www.lua.org/manual/5.1/manual.html#lua_call
>
> For a newbie (me, for instance), I don't think this documentation is clear
> enough about what you use for the nargs argument to lua_call() and therefore
> lua_pcall. At one point it says:
>
> "Finally you call lua_call; nargs is the number of arguments that you pushed
> onto the stack."
>
> While this is technically correct, the newbie might interpret this as the
> number of arguments taken by the Lua function. It isn't. It's that number of
> arguments plus one more that's used by the function name.

No, 'nargs' is exactly that - the number of ARGUMENTS you want to pass
to the function. You do not pass the function "name". Maybe this is a
bit confusing when coming to a language with first-class functions, but
you actually push the function itself on the stack.

> So if you interpret nargs as the number of args required by the Lua function
> and do this:
>
>     lua_getglobal(L, "tellme");
>     if (lua_pcall(L, 0, 0, 0))
> bail(L, "lua_pcall() failed");
>
> You get this at runtime:
> =================
> slitt@mydesk:~$ ./callfunc
> In C, calling Lua
>
> FATAL ERROR:
>   lua_pcall() failed: attempt to call a nil value

This is because there is no global named "tellme" (whose value should be
a function).

> Only if you read VERY carefully and concentrate on the documentation's saying
> "All arguments and the function value are popped from the stack when the
> function is called" do you get the idea that maybe nargs includes the pushed
> function name as well as the args required by the Lua function. In that case
> you do this:
>
>     lua_getglobal(L, "tellme");
>     if (lua_pcall(L, 1, 0, 0))
> bail(L, "lua_pcall() failed");
>
> And succeed:
> =================
> slitt@mydesk:~$ ./callfunc
> In C, calling Lua
> This is coming from lua.tellme.
> Back in C again
> slitt@mydesk:~$
> =================

You must have done something to your stack prior to this code, to have
accidentally included a function before this call. Let's take the code
from the manual:

a = f("how", t.x, 14)

Here it is in C:
     lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */
     lua_pushstring(L, "how");                        /* 1st argument */
     lua_getfield(L, LUA_GLOBALSINDEX, "t");   /* table to be indexed */
     lua_getfield(L, -1, "x");        /* push result of t.x (2nd arg) */
     lua_remove(L, -2);                  /* remove 't' from the stack */
     lua_pushinteger(L, 14);                          /* 3rd argument */
     lua_call(L, 3, 1);     /* call 'f' with 3 arguments and 1 result */
     lua_setfield(L, LUA_GLOBALSINDEX, "a");        /* set global 'a' */

At the beginning, the value of the global 'f' is pushed on the stack
(and we expect it to be a function). The call stack right before
lua_call is as follows:

1. function
2. "how"
3. value of t.x
4. 14

Then, you call lua_call(L, 3, 1). Notice that you pass 3 arguments, and
the 3 values from the top of the stack are passed as arguments. After
the call is finished, the 3 arguments are popped, together with the
function (not the "name", there is no such thing as function "name" in
Lua, there are only functions as values of named variables :). One
result is pushed onto the stack by lua_call, the value returned by the
function. This is assigned to the global "a".

You should often check the contents of the Lua stack while learning,
like with the function listed at http://www.lua.org/pil/24.2.3.html , to
get an idea how it is working - it is really simple in the end :)


Reply | Threaded
Open this post in threaded view
|

Re: Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Jerome Vuarand
In reply to this post by Steve Litt
2011/1/20 Steve Litt <[hidden email]>:
>    lua_getglobal(L, "tellme");
>    if (lua_pcall(L, 1, 0, 0))
>        bail(L, "lua_pcall() failed");

I think you got something wrong in your demonstration. That code is
not calling "tellme", which could still be nil (or any other
non-callable value). It's calling the function that was already on the
top of the stack before you called lua_getglobal. And the function
will receive exactly one argument, the value of the global "tellme"
variable.

Reply | Threaded
Open this post in threaded view
|

Re: Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Steve Litt
In reply to this post by Michal Kottman
On Thursday 20 January 2011 08:39:28 Michal Kottman wrote:
> On Thu, 2011-01-20 at 08:23 -0500, Steve Litt wrote:

> > You get this at runtime:
> > =================
> > slitt@mydesk:~$ ./callfunc
> > In C, calling Lua
> >
> > FATAL ERROR:
> >   lua_pcall() failed: attempt to call a nil value
>
> This is because there is no global named "tellme" (whose value should be
> a function).

What would make tellme a global? Here's my Lua script:

=======================
function tellme()
        io.write("This is coming from lua.tellme.\n")
end

function tellme2()
        io.write("This is coming from lua.tellmetwo.\n")
end

function witharg(n)
        io.write("Number within Lua.witharg=")
        io.write(tonumber(n))
        io.write("\n")
end

print("You shouldnt see this!")
=======================

Am I missing something? I thought the existence of a non-local function called
"tellme" within the script called by lua_pcall() would be the global function.

Thanks

SteveT

Steve Litt
Recession Relief Package
http://www.recession-relief.US
Twitter: http://www.twitter.com/stevelitt

Reply | Threaded
Open this post in threaded view
|

Re: Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Michal Kottman
On Thu, 2011-01-20 at 09:03 -0500, Steve Litt wrote:

> On Thursday 20 January 2011 08:39:28 Michal Kottman wrote:
> > On Thu, 2011-01-20 at 08:23 -0500, Steve Litt wrote:
>
> > > You get this at runtime:
> > > =================
> > > slitt@mydesk:~$ ./callfunc
> > > In C, calling Lua
> > >
> > > FATAL ERROR:
> > >   lua_pcall() failed: attempt to call a nil value
> >
> > This is because there is no global named "tellme" (whose value should be
> > a function).
>
> What would make tellme a global? Here's my Lua script:
>
> =======================
> function tellme()
> io.write("This is coming from lua.tellme.\n")
> end
>
> function tellme2()
> io.write("This is coming from lua.tellmetwo.\n")
> end
>
> function witharg(n)
> io.write("Number within Lua.witharg=")
> io.write(tonumber(n))
> io.write("\n")
> end
>
> print("You shouldnt see this!")
> =======================
>
> Am I missing something? I thought the existence of a non-local function called
> "tellme" within the script called by lua_pcall() would be the global function.

Well, this should work. But there is something you maybe don't
understand. Functions don't exist, until you actually create them. In
Lua, function abcd() end is syntax sugar for this:

abcd = function() end

So in order to "have" the functions in the global table, you need to run
the code (so that they are created and assigned). You will actually need
to see the "You shouldnt see this!" text to have them available.

In C, you can call luaL_dofile(filename) to run the code prior to your
calling of "tellme". lua_loadfile actually only compiles the file as a
function and prepares for you to run it (maybe that is why you had a
function in your stack available).


Reply | Threaded
Open this post in threaded view
|

Re: Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Axel Kittenberger
In reply to this post by Steve Litt
"To call a function you must use the following protocol: first, the
function to be called is pushed onto the stack; then, the arguments to
the function are pushed in direct order"

I dont see any confusing in this. And as others point out, you push
the function itself on the stack not "the name". Its comparable to a
function pointer in C.

Reply | Threaded
Open this post in threaded view
|

Can't call Lua Function <SOLVED>, was Possible documentation improvement on Lua 5.1 Reference Manual, lua_call()

Steve Litt
In reply to this post by Michal Kottman
On Thursday 20 January 2011 09:17:51 Michal Kottman wrote:

> On Thu, 2011-01-20 at 09:03 -0500, Steve Litt wrote:
> > On Thursday 20 January 2011 08:39:28 Michal Kottman wrote:
> > > On Thu, 2011-01-20 at 08:23 -0500, Steve Litt wrote:
> > > > You get this at runtime:
> > > > =================
> > > > slitt@mydesk:~$ ./callfunc
> > > > In C, calling Lua
> > > >
> > > > FATAL ERROR:
> > > >   lua_pcall() failed: attempt to call a nil value
> > >
> > > This is because there is no global named "tellme" (whose value should
> > > be a function).
> >
> > What would make tellme a global? Here's my Lua script:
> >
> > =======================
> > function tellme()
> > io.write("This is coming from lua.tellme.\n")
> > end
> >
> > function tellme2()
> > io.write("This is coming from lua.tellmetwo.\n")
> > end
> >
> > function witharg(n)
> > io.write("Number within Lua.witharg=")
> > io.write(tonumber(n))
> > io.write("\n")
> > end
> >
> > print("You shouldnt see this!")
> > =======================
> >
> > Am I missing something? I thought the existence of a non-local function
> > called "tellme" within the script called by lua_pcall() would be the
> > global function.
>
> Well, this should work. But there is something you maybe don't
> understand. Functions don't exist, until you actually create them. In
> Lua, function abcd() end is syntax sugar for this:
>
> abcd = function() end

THE KEY POINT FOLLOWS...
 
> So in order to "have" the functions in the global table, you need to run
> the code (so that they are created and assigned). You will actually need
> to see the "You shouldnt see this!" text to have them available.
>
> In C, you can call luaL_dofile(filename) to run the code prior to your
> calling of "tellme". lua_loadfile actually only compiles the file as a
> function and prepares for you to run it (maybe that is why you had a
> function in your stack available).

THAT SOLVED IT!

You need to run the script once in order to create and assign the functions as
globals.

Thank you Michal. It was driving me nuts.

I did this:

/* Execute script once to create and assign functions */
if (lua_pcall(L, 0, 0, 0))
        bail(L, "lua_pcall() failed");

printf("In C, calling Lua\n");

/* Specify which function to run */
lua_getfield(L, LUA_GLOBALSINDEX, "tellme");

/* Now run it */
if (lua_pcall(L, 0, 0, 0))
        bail(L, "lua_pcall() failed");

printf("Back in C again\n");


Once again for the sake of newbies, I think it would help to add a sentence to
the lua_call() docs in the manual saying you must run dofile() or lua_pcall()
first without a function to get all the functions registered as globals.
Nobody on the Internet says that explicitly, at least nobody I was able to
Google within 2 hours.

Again, thank you -- it was driving me nuts.

SteveT

Steve Litt
Recession Relief Package
http://www.recession-relief.US
Twitter: http://www.twitter.com/stevelitt