diff --git a/src/api/l_math.c b/src/api/l_math.c index 46ebe979..5300c826 100644 --- a/src/api/l_math.c +++ b/src/api/l_math.c @@ -295,7 +295,7 @@ int luaopen_lovr_math(lua_State* L) { luax_registertype(L, RandomGenerator); for (int i = 0; i < MAX_MATH_TYPES; i++) { - _luax_registertype(L, lovrMathTypeNames[i], lovrMathTypes[i]); + _luax_registertype(L, lovrMathTypeNames[i], lovrMathTypes[i], NULL); luaL_getmetatable(L, lovrMathTypeNames[i]); // Remove usual __gc handler diff --git a/src/core/luax.c b/src/core/luax.c index 2e741493..b8c42f69 100644 --- a/src/core/luax.c +++ b/src/core/luax.c @@ -13,7 +13,14 @@ static int luax_meta__tostring(lua_State* L) { static int luax_meta__gc(lua_State* L) { Proxy* p = lua_touserdata(L, 1); - lovrGenericRelease(p->object); + if (p) { + lua_getmetatable(L, 1); + lua_getfield(L, -1, "__destructor"); + lovrDestructor* destructor = (lovrDestructor*) lua_tocfunction(L, -1); + if (destructor) { + _lovrRelease(destructor, p->object); + } + } return 0; } @@ -101,7 +108,7 @@ void luax_registerloader(lua_State* L, lua_CFunction loader, int index) { lua_pop(L, 1); } -void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions) { +void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions, lovrDestructor* destructor) { // Push metatable luaL_newmetatable(L, name); @@ -115,6 +122,10 @@ void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* function lua_pushcfunction(L, luax_meta__gc); lua_setfield(L, -2, "__gc"); + // m.__destructor = destructor (used to release reference) + lua_pushcfunction(L, (lua_CFunction) destructor); + lua_setfield(L, -2, "__destructor"); + // m.name = name lua_pushstring(L, name); lua_setfield(L, -2, "name"); @@ -132,8 +143,8 @@ void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* function lua_pop(L, 1); } -void _luax_extendtype(lua_State* L, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions) { - _luax_registertype(L, name, functions); +void _luax_extendtype(lua_State* L, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions, lovrDestructor* destructor) { + _luax_registertype(L, name, functions, destructor); luaL_getmetatable(L, name); luaL_register(L, NULL, baseFunctions); lua_pop(L, 1); diff --git a/src/core/luax.h b/src/core/luax.h index f63c3985..26736ff0 100644 --- a/src/core/luax.h +++ b/src/core/luax.h @@ -17,8 +17,8 @@ typedef struct { #endif #define luax_len(L, i) (int) lua_objlen(L, i) -#define luax_registertype(L, T) _luax_registertype(L, #T, lovr ## T) -#define luax_extendtype(L, S, T) _luax_extendtype(L, #T, lovr ## S, lovr ## T) +#define luax_registertype(L, T) _luax_registertype(L, #T, lovr ## T, lovr ## T ## Destroy) +#define luax_extendtype(L, S, T) _luax_extendtype(L, #T, lovr ## S, lovr ## T, lovr ## T ## Destroy) #define luax_totype(L, i, T) ((T*) _luax_totype(L, i, T_ ## T)) #define luax_checktype(L, i, T) ((T*) _luax_checktype(L, i, T_ ## T, #T)) #define luax_checkfloat(L, i) (float) luaL_checknumber(L, i) @@ -32,8 +32,8 @@ int luax_print(lua_State* L); void luax_setmainthread(lua_State* L); void luax_atexit(lua_State* L, luax_destructor destructor); void luax_registerloader(lua_State* L, lua_CFunction loader, int index); -void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions); -void _luax_extendtype(lua_State* L, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions); +void _luax_registertype(lua_State* L, const char* name, const luaL_Reg* functions, lovrDestructor* destructor); +void _luax_extendtype(lua_State* L, const char* name, const luaL_Reg* baseFunctions, const luaL_Reg* functions, lovrDestructor* destructor); void* _luax_totype(lua_State* L, int index, Type type); void* _luax_checktype(lua_State* L, int index, Type type, const char* debug); void luax_pushobject(lua_State* L, void* object); diff --git a/src/core/types.h b/src/core/types.h index 455d25fb..d16ad500 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -86,3 +86,4 @@ void* _lovrAlloc(size_t size, Type type); #define lovrRetain(o) if (o && refcount_increment(_ref(o)->count) >= 0xff) lovrThrow("Ref count overflow") #define lovrRelease(T, o) if (o && refcount_decrement(_ref(o)->count) == 0) lovr ## T ## Destroy(o), free(_ref(o)) #define lovrGenericRelease(o) if (o && refcount_decrement(_ref(o)->count) == 0) lovrTypeInfo[_ref(o)->type].destructor(o), free(_ref(o)) +#define _lovrRelease(f, o) if (o && refcount_decrement(_ref(o)->count) == 0) f(o), free(_ref(o))