lua-users home
lua-l archive

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


Hi,

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.

Thanks.