lua-users home
lua-l archive

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



>     lua_settop(L, 2);   /* as before, zap extra args if any */

> There's no need for this in common usage.
> lua_settop is only needed to remove unwanted *return* values from
functions
> called inside loops.
> lua_settop is also used to set absent argumens to nil.

Maybe I'm confused, but I was under the impression that a C function had no
way to predefine the number of arguments it was being handed. I need the
second
argument to be on the top of the stack for the following call to lua_ref()
to work,
so the easiest way to get there is lua_settop()... otherwise, as I
understand it,
I'm going to end up with a ref to whatever the last argument happened to
be.

> >PD: I actually recommend not putting stuff like that in globals, since
it
> >is relative to a lua_State. Using globals means that whatever you write
> >will only work in a single lua_State, which may prove limiting later on.

> So, use the registry, which was created exactly for this.
> --lhf

That would be one way to do it, yes. I also often find myself creating
closures with state information in them, although that technique might not
be effective in this particular case... not my program, so I don't know
what he's after exactly....

It's true that using the registry would avoid the need to create (and then
clean up) a lua_ref, so it has a number of advantages.

I've been working on a Lua wrapper for the readline library, and have had
to resort to a global there, although I could equally well have used the
registry. The problem with callbacks from non-reentrant code is that you
probably have no way to even tell the callback what the lua_State* is,
which
means you're limited to a single active lua_State. That's not a problem
with
Lua, rather with non-reentrant libraries that use callbacks.

A better readline interface would have given me a chance to pass a single
pointer through to my callback; in that case, I might choose to pass the
lua_State* and use the registry to get my state information. That would
only leave me with the problem of figuring out a bullet-proof convention
for registry keys guaranteed not to conflict with other people's keys.
Maybe
I shouldn't worry so much about stuff like that.

So the code would look a bit like this...

     // Saving the function
     ...
     lua_getregistry(L);
     lua_pushstring(L, "myTimerLibrary_wait_function");
     lua_pushvalue(L, 2);     /* now I don't need lua_settop :-) */
     lua_rawset(L, -3);
     ...

     // calling the function
     ...
     lua_getregistry(L);
     lua_pushstring(L, "myTimerLibrary_wait_function");
     lua_rawget(L, -2);
          // should check for failure at this point
     if (lua_rawcall(L, 0, 0)) {
          // handle error somehow
     }
     ....

     // Now it's not strictly necessary to clean things up

Alternatively, I could have created a table and used the registry key
myTimerLibrary to get the table; then waitFunction could have been a key
in that table. That would arguably be cleaner.

So I guess the solution did fit in the margin of an e-mail :-)

Rici

PD:
Thinking about it, the original version with lua_ref's should have
checked to make sure that there wasn't an existing lua_ref:

     ...
         if (g_waitFnRef != LUA_NOREF) lua_unref(L, g_waitFnRef);
          g_waitFnRef = lua_ref(L, 1);
     ...