[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: C upvalue cleanup not being called
- From: David Crayford <dcrayford@...>
- Date: Tue, 11 Mar 2014 21:46:53 +0800
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;
}