diff --git a/sol/lua_function.hpp b/sol/lua_function.hpp index e2bd98ca..c69941e7 100644 --- a/sol/lua_function.hpp +++ b/sol/lua_function.hpp @@ -24,6 +24,7 @@ #include "functional.hpp" #include "stack.hpp" +#include namespace sol { @@ -112,13 +113,24 @@ struct static_object_lua_func { struct lua_func { static int call(lua_State* L) { - void* inheritancedata = lua_touserdata(L, lua_upvalueindex(1)); + void** pinheritancedata = static_cast(lua_touserdata(L, lua_upvalueindex(1))); + void* inheritancedata = *pinheritancedata; if (inheritancedata == nullptr) throw sol_error("call from lua to c++ function has null data"); - lua_func& fx = *static_cast(inheritancedata); + lua_func* pfx = static_cast(inheritancedata); + lua_func& fx = *pfx; int r = fx(L); return r; } + + static int gc(lua_State* L) { + void** puserdata = static_cast(lua_touserdata(L, 1)); + void* userdata = *puserdata; + lua_func* ptr = static_cast(userdata); + std::default_delete dx{ }; + dx(ptr); + return 0; + } virtual int operator()(lua_State*) { throw sol_error("Failure to call specialized wrapped C++ function from lua"); @@ -152,6 +164,10 @@ struct lambda_lua_func : public lua_func { stack::push(L, r); return sizeof...(TRn); } + + ~lambda_lua_func() { + + } }; template::value> @@ -179,6 +195,10 @@ struct explicit_lua_func : public lua_func { stack::push(L, std::move(r)); return sizeof...(TRn); } + + ~explicit_lua_func() { + + } }; template @@ -199,7 +219,7 @@ struct explicit_lua_func : public lua_func { } fx; template - explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move( m ), std::forward(fxargs)...) {} + explicit_lua_func(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward(fxargs)...) {} virtual int operator()(lua_State* L) override { return (*this)(tuple_types(), typename fx_traits::args_type(), L); @@ -217,6 +237,10 @@ struct explicit_lua_func : public lua_func { stack::push(L, r); return sizeof...(TRn); } + + ~explicit_lua_func() { + + } }; } // sol diff --git a/sol/stack.hpp b/sol/stack.hpp index bb6baaec..925cf9a9 100644 --- a/sol/stack.hpp +++ b/sol/stack.hpp @@ -165,6 +165,17 @@ inline void push(lua_State* L, const std::string& str) { lua_pushlstring(L, str.c_str(), str.size()); } +template +inline void push_user(lua_State* L, T& userdata, const char* metatablekey) { + T* pdatum = static_cast(lua_newuserdata(L, sizeof(T))); + T& datum = *pdatum; + datum = userdata; + if (metatablekey != nullptr) { + lua_getfield(L, LUA_REGISTRYINDEX, metatablekey); + lua_setmetatable(L, -2); + } +} + template inline void push(lua_State* L, const std::array& data) { for (auto&& i : data) { diff --git a/sol/table.hpp b/sol/table.hpp index e1272208..e19ef713 100644 --- a/sol/table.hpp +++ b/sol/table.hpp @@ -24,9 +24,7 @@ #include "stack.hpp" #include "lua_function.hpp" -#include #include -#include #include namespace sol { @@ -122,7 +120,7 @@ private: template table& set_lvalue_fx(std::false_type, T&& key, TFx&& fx, TObj&& obj) { typedef typename std::remove_pointer::type>::type clean_fx; - std::unique_ptr sptr(new explicit_lua_func(std::forward( obj ), std::forward(fx))); + std::unique_ptr sptr(new explicit_lua_func(std::forward(obj), std::forward(fx))); return set_fx(std::forward(key), std::move(sptr)); } @@ -173,7 +171,7 @@ private: const char* freefuncname = fkey.c_str(); const luaL_Reg funcreg[ 2 ] = { { freefuncname, freefunc }, - { nullptr, nullptr } + { nullptr, nullptr } }; push(); @@ -188,33 +186,31 @@ private: template table& set_fx(T&& key, std::unique_ptr luafunc) { std::string fkey(key); - - lua_func* target = luafunc.release(); + std::string metakey("sol.stateful."); + metakey += fkey; + metakey += ".meta"; + lua_func* target = luafunc.release(); void* userdata = reinterpret_cast(target); lua_CFunction freefunc = &lua_func::call; const char* freefuncname = fkey.c_str(); + const char* metatablename = metakey.c_str(); const luaL_Reg funcreg[2] = { { freefuncname, freefunc }, - { nullptr, nullptr } - }; - - push(); + { nullptr, nullptr } + }; - // Actual function call we want - stack::push( state(), userdata ); - luaL_setfuncs(state(), funcreg, 1); - + int exists = luaL_newmetatable(state(), metatablename); + lua_pushstring(state(), "__gc"); + lua_pushcclosure(state(), &lua_func::gc, 0); + lua_settable(state(), -3); + push(); + + stack::push_user(state(), userdata, metatablename); + luaL_setfuncs(state(), funcreg, 1); + lua_pop(state(), 1); return *this; } - - static int destroyfunc( lua_State* L ) { - void* userdata = lua_touserdata( L, 1 ); - lua_func* ptr = static_cast( userdata ); - std::default_delete dx{ }; - dx( ptr ); - return 0; - } }; } // sol