Last active
August 29, 2015 14:00
-
-
Save ThePhD/11298310 to your computer and use it in GitHub Desktop.
lua_class.c++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace sol { | |
template <typename... Tn> | |
struct constructors { }; | |
template <typename T> | |
class lua_class { | |
public: | |
static const std::string classname; | |
static const std::string meta; | |
private: | |
std::string luaname; | |
std::vector<std::string> functionnames; | |
std::vector<std::unique_ptr<lua_func>> functions; | |
std::vector<luaL_Reg> functiontable; | |
std::vector<luaL_Reg> metatable; | |
struct maker { | |
static int construct( lua_State* L ) { | |
// First argument is now a table that represent the class to instantiate | |
luaL_checktype( L, 1, LUA_TTABLE ); | |
lua_newtable( L ); // Create table to represent instance | |
// Set first argument of new to metatable of instance | |
lua_pushvalue( L, 1 ); | |
lua_setmetatable( L, -2 ); | |
// Do function lookups in metatable | |
lua_pushvalue( L, 1 ); | |
lua_setfield( L, 1, "__index" ); | |
void* userdata = lua_newuserdata( L, sizeof( T ) ); | |
T* obj = static_cast<T*>( userdata ); | |
std::allocator<T> alloc{ }; | |
alloc.construct( obj ); | |
} | |
template <std::size_t n> | |
static int destruct( lua_State* L ) { | |
for ( std::size_t i = 0; i < n; ++i ) { | |
stack::pop<light_user_data>( L, i ); | |
} | |
void* userdata = lua_touserdata( L, 0 ); | |
T* obj = static_cast<T*>( userdata ); | |
std::allocator<T> alloc{ }; | |
alloc.destroy( obj ); | |
} | |
}; | |
void build_function_tables( ) { | |
} | |
template <typename... Args, typename Ret, typename... MArgs> | |
void build_function_tables( Ret( T::* func )( MArgs... ), std::string name, Args&&... args ) { | |
typedef typename std::decay<decltype( func )>::type fx_t; | |
functionnames.push_back( std::move( name ) ); | |
functions.emplace_back( std::make_unique<class_lua_func<fx_t, T>>( std::move( func ) ) ); | |
functiontable.push_back( { functionnames.back().c_str(), &lua_func::call } ); | |
build_function_tables( std::forward<Args>( args )... ); | |
} | |
public: | |
template <typename... Args> | |
lua_class( Args&&... args ) : lua_class( classname, std::forward<Args>( args )... ) { | |
} | |
template <typename... Args> | |
lua_class( std::string name, Args&&... args ) : lua_class( name, constructors<>( ), std::forward<Args>( args )... ) { | |
} | |
template <typename... Args, typename... CArgs> | |
lua_class( constructors<CArgs...> c, Args&&... args ) : lua_class( classname, std::move( c ), std::forward<Args>( args )... ) { | |
} | |
template <typename... Args, typename... CArgs> | |
lua_class( std::string name, constructors<CArgs...> c, Args&&... args ) : luaname( std::move( name ) ) { | |
functionnames.reserve( sizeof...( args ) ); | |
functiontable.reserve( sizeof...( args ) ); | |
functions.reserve( sizeof...( args ) ); | |
metatable.reserve( sizeof...( args ) ); | |
build_function_tables( std::forward<Args>( args )... ); | |
functionnames.push_back( "new" ); | |
functiontable.push_back( { functionnames.back( ).c_str( ), &maker::construct } ); | |
functiontable.push_back( { nullptr, nullptr } ); | |
// ERROR: error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'lua_CFunction' | |
metatable.push_back( { "__gc", &maker::destruct<sizeof...( Args ) / 2> } ); | |
metatable.push_back( { nullptr, nullptr } ); | |
} | |
}; | |
template <typename T> | |
const std::string lua_class<T>::classname = detail::demangle( typeid( T ) ); | |
template <typename T> | |
const std::string lua_class<T>::meta = std::string( "sol.stateful." ).append( classname ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment