From 4c102605e8739b83da3f8b3d5b05dfb4b356113d Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sat, 26 Apr 2014 00:19:36 -0400 Subject: [PATCH] Custom constructors, but apparently there's something on the stack and we can't get at its type? --- sol/demangle.hpp | 23 ++++++++++++------ sol/userdata.hpp | 63 ++++++++++++++++++++++++++++++++++-------------- 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/sol/demangle.hpp b/sol/demangle.hpp index d2ef43b7..af271ef2 100644 --- a/sol/demangle.hpp +++ b/sol/demangle.hpp @@ -23,6 +23,7 @@ #define SOL_DEMANGLE_HPP #include +#include #if defined(__GNUC__) || defined(__clang__) #include @@ -32,16 +33,22 @@ namespace sol { namespace detail { #ifdef _MSC_VER std::string demangle(const std::type_info& id) { - const static std::string removals[2] = { "struct ", "class " }; - std::string realname = id.name(); - for(std::size_t r = 0; r < 2; ++r) { + const static std::array removals = { "struct ", "class " }; + const static std::array replacements = { "::", "_" }; + std::string realname = id.name( ); + for(std::size_t r = 0; r < removals.size(); ++r) { auto found = realname.find(removals[r]); - - if(found == std::string::npos) { - continue; + while (found != std::string::npos) { + realname.erase(found, removals[r].size()); + found = realname.find( removals[r] ); + } + } + for(std::size_t r = 0; r < replacements.size(); r+=2) { + auto found = realname.find(replacements[r]); + while (found != std::string::npos) { + realname.replace(found, replacements[r].size(), replacements[r+1]); + found = realname.find(replacements[r], found); } - - realname.erase(found, removals[r].size()); } return realname; } diff --git a/sol/userdata.hpp b/sol/userdata.hpp index 8f211610..70433367 100644 --- a/sol/userdata.hpp +++ b/sol/userdata.hpp @@ -47,14 +47,39 @@ private: std::vector> functions; std::vector functiontable; std::vector metatable; - + + template struct constructor { + template + static void do_constructor(lua_State* L, T* obj, int argcount, types t) { + auto fx = [&obj] ( Args&&... args ) -> void { + std::allocator alloc{}; + alloc.construct(obj, std::forward(args)...); + }; + stack::pop_call(L, fx, t); + } + + static void match_constructor(lua_State* L, T* obj, int argcount) { + if (argcount != 0) + throw sol_error("No matching constructor for the arguments provided"); + } + + template + static void match_constructor(lua_State* L, T* obj, int argcount, types t, Args&&... args) { + if (argcount == sizeof...(CArgs)) { + do_constructor( L, obj, argcount, t ); + return; + } + match_constructor( L, obj, argcount, std::forward(args)...); + } + static int construct(lua_State* L) { + int argcount = lua_gettop(L); // First argument is now a table that represent the class to instantiate - luaL_checktype(L, 1, LUA_TTABLE); - - lua_createtable(L, 0, 0); // Create table to represent instance - + luaL_checktype( L, 1, LUA_TTABLE ); + + // Table represents the instance + lua_createtable(L, 0, 0); // Set first argument of new to metatable of instance lua_pushvalue(L, 1); lua_setmetatable(L, -2); @@ -63,16 +88,17 @@ private: lua_pushvalue(L, 1); lua_setfield(L, 1, "__index"); - void* userdata = lua_newuserdata(L, sizeof(T)); - T* obj = static_cast(userdata); - std::allocator alloc{}; - alloc.construct(obj); - luaL_getmetatable(L, meta.c_str()); + void* udata = lua_newuserdata( L, sizeof( T ) ); + T* obj = static_cast( udata ); + match_constructor( L, obj, argcount - 1, std::common_type::type( )... ); + //match_constructor( L, obj, argcount - 1, types( ) ); + + luaL_getmetatable(L, meta.c_str()); lua_setmetatable(L, -2); lua_setfield(L, -2, "__self"); - return 1; + return 1; } }; @@ -80,13 +106,14 @@ private: struct destructor { static int destruct(lua_State* L) { for(std::size_t i = 0; i < n; ++i) { - lightuserdata_t luserdata = stack::get(L, i); - // make warnings shut up - (void)luserdata; + lightuserdata_t ludata = stack::get(L, i); + lua_func* func = static_cast(ludata.value); + std::default_delete dx{}; + dx(func); } - userdata_t userdata = stack::get(L, 0); - T* obj = static_cast(userdata.value); + userdata_t udata = stack::get(L, 0); + T* obj = static_cast(udata.value); std::allocator alloc{}; alloc.destroy(obj); @@ -127,7 +154,7 @@ public: userdata(Args&&... args) : userdata(classname, std::forward(args)...) {} template - userdata(std::string name, Args&&... args) : userdata(name, constructors<>(), std::forward(args)...) {} + userdata(std::string name, Args&&... args) : userdata(name, constructors>(), std::forward(args)...) {} template userdata(constructors c, Args&&... args) : userdata(classname, std::move(c), std::forward(args)...) {} @@ -141,7 +168,7 @@ public: build_function_tables<0>(std::forward(args)...); functionnames.push_back("new"); - functiontable.push_back({ functionnames.back().c_str(), &constructor::construct }); + functiontable.push_back({ functionnames.back().c_str(), &constructor::construct }); functiontable.push_back({ nullptr, nullptr }); metatable.push_back({ "__gc", &destructor::destruct });