lua-users home
lua-l archive

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


2016-10-31 4:58 GMT+02:00 dl acc <nydlacc123@gmail.com>:

> I'm hoping for a bit of confirmation that my understanding of how Lua passes
> arguments to __unm is correct. I have a library that dispatches to the
> correct C++ function depending on the contents of the Lua stack. It checks
> that the number and type of the Lua data on the stack is appropriate for the
> C++ function being called.
>
> Everything was working until I got an unexpected failure after setting a C++
> function to be called as the unary minus operation of a userdata. The Lua
> documentation says that the __unm handler is called as handler(operand) so I
> wrote the C++ function to take one argument and therefore one value should
> be on the Lua stack when it is invoked as a lua_CFunction. However, two
> values were on the stack instead and so my library refused to call the
> one-argument C++ function in that case.
>
> I rebuilt with both Luajit and Lua 5.3 and got the same behavior so I did a
> bit of digging and found this in lapi.c
>
> LUA_API void lua_arith (lua_State *L, int op) {
>   lua_lock(L);
>   if (op != LUA_OPUNM && op != LUA_OPBNOT)
>     api_checknelems(L, 2);  /* all other operations expect two operands */
>   else {  /* for unary operations, add fake 2nd operand */
>     api_checknelems(L, 1);
>     setobjs2s(L, L->top, L->top - 1);
>     api_incr_top(L);
>   }
>   /* first operand at top - 2, second at top - 1; result go to top - 2 */
>   luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2);
>   L->top--;  /* remove second operand */
>   lua_unlock(L);
> }
>
> It seems that the addition of the "fake" operand is reason for the
> unexpected extra value on the stack. Is my understanding correct? I can
> accomodate this by rewriting my C++ __unm handler to take two arguments
> instead and ignore the second one. Of course, it will break if this Lua
> implementation detail changes in the future. Alternatively my library could
> stop requiring an exact match for the number of parameters, instead allowing
> the call if at least as many Lua values as there are C++ parameters is on
> the stack. I don't really want to do that though, because the library allows
> overloading so not requiring an exact match of parameter counts and Lua
> stack size complicates the set of applicable functions.

"For the unary operators (negation, length, and bitwise not), the metamethod
is computed and called with a dummy second operand, equal to the first one.
This extra operand is only to simplify Lua's internals (by making
these operators
behave like a binary operation) and may be removed in future versions.
(For most uses this extra operand is irrelevant.)"  -- Lua 5.3 User's Manual