Lua userdata store their destructor in their metatable;

This commit is contained in:
bjorn 2019-05-28 15:15:12 -07:00
parent 5ec6f1d1d1
commit d11e9be175
4 changed files with 21 additions and 9 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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))