diff --git a/VM/include/lua.h b/VM/include/lua.h index 3f5e99f4..e49e6ad9 100644 --- a/VM/include/lua.h +++ b/VM/include/lua.h @@ -313,7 +313,11 @@ LUA_API uintptr_t lua_encodepointer(lua_State* L, uintptr_t p); LUA_API double lua_clock(); LUA_API void lua_setuserdatatag(lua_State* L, int idx, int tag); -LUA_API void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*)); + +typedef void (*lua_Destructor)(lua_State* L, void* userdata); + +LUA_API void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor); +LUA_API lua_Destructor lua_getuserdatadtor(lua_State* L, int tag); LUA_API void lua_clonefunction(lua_State* L, int idx); diff --git a/VM/src/lapi.cpp b/VM/src/lapi.cpp index 1528aa39..08d64d55 100644 --- a/VM/src/lapi.cpp +++ b/VM/src/lapi.cpp @@ -1378,12 +1378,18 @@ void lua_setuserdatatag(lua_State* L, int idx, int tag) uvalue(o)->tag = uint8_t(tag); } -void lua_setuserdatadtor(lua_State* L, int tag, void (*dtor)(lua_State*, void*)) +void lua_setuserdatadtor(lua_State* L, int tag, lua_Destructor dtor) { api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); L->global->udatagc[tag] = dtor; } +lua_Destructor lua_getuserdatadtor(lua_State* L, int tag) +{ + api_check(L, unsigned(tag) < LUA_UTAG_LIMIT); + return L->global->udatagc[tag]; +} + void lua_clonefunction(lua_State* L, int idx) { luaC_checkGC(L); diff --git a/VM/src/ludata.cpp b/VM/src/ludata.cpp index c2110cb3..13e87029 100644 --- a/VM/src/ludata.cpp +++ b/VM/src/ludata.cpp @@ -24,8 +24,7 @@ void luaU_freeudata(lua_State* L, Udata* u, lua_Page* page) { if (u->tag < LUA_UTAG_LIMIT) { - void (*dtor)(lua_State*, void*) = nullptr; - dtor = L->global->udatagc[u->tag]; + lua_Destructor dtor = L->global->udatagc[u->tag]; // TODO: access to L here is highly unsafe since this is called during internal GC traversal // certain operations such as lua_getthreaddata are okay, but by and large this risks crashes on improper use if (dtor) diff --git a/tests/Conformance.test.cpp b/tests/Conformance.test.cpp index 2a32bce2..0a9d1f77 100644 --- a/tests/Conformance.test.cpp +++ b/tests/Conformance.test.cpp @@ -1352,9 +1352,14 @@ TEST_CASE("UserdataApi") lua_State* L = globalState.get(); // setup dtor for tag 42 (created later) - lua_setuserdatadtor(L, 42, [](lua_State* l, void* data) { + auto dtor = [](lua_State* l, void* data) { dtorhits += *(int*)data; - }); + }; + bool dtorIsNull = lua_getuserdatadtor(L, 42) == nullptr; + CHECK(dtorIsNull); + lua_setuserdatadtor(L, 42, dtor); + bool dtorIsSet = lua_getuserdatadtor(L, 42) == dtor; + CHECK(dtorIsSet); // light user data int lud;