lua-users home
lua-l archive

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


I copied some code from another module that works ok but does not call the __gc callback for a userdata. I'm stumped. I'm a newbie with the C API but suspect it may have something to do with the lua_setfuncs() compatibility function (I'm using Lua 5.1). TBH, I'm not sure if this is even the best way to achieve what I want. What's the best way to register a cleanup handler for userdata?


#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
/* Compatibility for Lua 5.1.
 *
* luaL_setfuncs() is used to create a module table where the functions have * ispf_config_t as their first upvalue. Code borrowed from Lua 5.2 source. */
static void luaL_setfuncs( lua_State * l, const luaL_Reg * reg, int nup )
{
    int i;
    luaL_checkstack( l, nup, "too many upvalues" );
for (; reg->name != NULL; reg++ ) /* fill the table with given functions */
    {
        for ( i = 0; i < nup; i++ )       /* copy upvalues to the top */
            lua_pushvalue( l, -nup );
lua_pushcclosure( l, reg->func, nup ); /* closure with those upvalues */
        lua_setfield( l, -( nup + 2 ), reg->name );
    }
    lua_pop( l, nup );  /* remove upvalues */
}
#endif

static int destroy_config( lua_State * L ) // not being called
{
    ispf_config_t * ispf = fetch_config( L );
    printf( "ispexec=%p\n", ispf->ispexec );
    return 1;
}

extern "C" int luaopen_ispf( lua_State * L )
{
    luaL_Reg reg[] = {
        { "bind", ispf_bind },
        { "ispexec", ispf_exec },
        { "vcopy", ispf_vcopy },
        { "vreplace", ispf_vreplace },
        { NULL, NULL }

    };

    // module table
    lua_newtable( L );

    // register functions with config data as upvalue
ispf_config_t * config = ( ispf_config_t * )lua_newuserdata( L, sizeof*config );

    config->isplink = ( isplink_t * )( fetch( "ISPLINK" ) );
    config->ispexec = ( ispexec_t * )( fetch( "ISPEXEC" ) );

    // create GC method to clean up loaded functions
    lua_newtable( L );
    lua_pushcfunction( L, destroy_config );
    lua_setfield( L, -2, "__gc" );
    lua_setmetatable( L, -2 );

    luaL_setfuncs( L, reg, 1 );

    // set module name / version fields
    lua_pushliteral( L, ISPF_MODNAME );
    lua_setfield( L, -2, "_NAME" );
    lua_pushliteral( L, ISPF_VERSION );
    lua_setfield( L, -2, "_VERSION" );

    return 1;
}