lua-users home
lua-l archive

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



On 16/02/17 07:28 PM, tobias@justdreams.de wrote:

Hi,


I came across an odd behaviour where the call to a __len function has 2 identical stack items. I also tested __tostring and it does have only one item. Test code:


len_fail.c
// vim: ts=4 sw=4 st=4 sta tw=80 list
#include <stdio.h>
#include <string.h>

#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#define  FOO_TYPE  "TYPE_OF_FOO"

// compile:
// gcc -O3 -Wall -Werror -I/usr/include len_fail.c -o len_fail -llua

lua_State  *L;

typedef struct Foo {
    size_t  len;
} Foo;

const char luascript [] = {
    "print(  uservalue ) -- invokes tostring\n"
    "print( type( uservalue ) )\n"
    "print( 'Length:',   #uservalue )\n"
};

// meta function
static int f__len( lua_State *L )
{
    printf( "STACKSIZE SHOULD BE 1 but is %d\n", lua_gettop( L ) );
    Foo *foo1 = (Foo *) luaL_checkudata( L, 1, FOO_TYPE );
    // this prooves the second stack item is the same as the first
    Foo *foo2 = (Foo *) luaL_checkudata( L, 2, FOO_TYPE );
    printf( "Found items: 1[%p]  2[%p]\n", foo1, foo2 );
    lua_pushinteger( L, foo1->len );
    return 1;
}

static int f__tostring( lua_State *L )
{
    printf( "STACKSIZE SHOULD BE 1 and is %d\n", lua_gettop( L ) );
    Foo *foo = (Foo *) luaL_checkudata( L, 1, FOO_TYPE );
    lua_pushfstring( L, FOO_TYPE"[%d]: %p", foo->len, foo );
    return 1;
}

static const luaL_Reg foo_m [] = {
      { "__len"        , f__len }
    , { "__tostring"   , f__tostring }
    , { NULL           , NULL}
};

int main ( int argc, char *argv[] )
{
    argc=argc;
    argv[0]=argv[0];  // make -Wall -Werror happy

    L = luaL_newstate();
    luaL_openlibs(L);

    Foo *foo = (Foo *) lua_newuserdata(L, sizeof (Foo));
    foo->len = 12;

    luaL_newmetatable( L, FOO_TYPE );
    luaL_setfuncs( L, foo_m, 0 );
    lua_setmetatable( L, -2 );

    lua_setglobal( L, "uservalue" );

    luaL_loadstring( L, luascript );
    if (lua_pcall( L, 0, LUA_MULTRET, 0 ))
        printf( "%s\n", lua_tostring(L, -1) );

    // cleanup Lua
    lua_close(L);

    return 0;
}



And here is the output:

[arch@tk lua_sample]$ ./len_fail
STACKSIZE SHOULD BE 1 but is 1
TYPE_OF_FOO[12]: 0xcbebc8
userdata
STACKSIZE SHOULD BE 1 but is 2
Found items: 1[0xcbebc8]  2[0xcbebc8]
Length:    12
[arch@tk lua_sample]$


Thoughts?

 -Tobias



Also with unm and bnot:

"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.)"

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.