Merge remote-tracking branch 'root/classes'

This commit is contained in:
ThePhD 2014-04-26 00:19:45 -04:00
commit 4d6d39be88
5 changed files with 68 additions and 103 deletions

View File

@ -28,7 +28,7 @@
namespace sol { namespace sol {
template<typename Function> template<typename Function>
struct static_lua_func { struct static_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type; typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type; typedef function_traits<function_type> traits_type;
@ -64,7 +64,7 @@ struct static_lua_func {
}; };
template<typename T, typename Function> template<typename T, typename Function>
struct static_object_lua_func { struct static_member_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type; typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type; typedef function_traits<function_type> traits_type;
@ -103,15 +103,15 @@ struct static_object_lua_func {
} }
}; };
struct lua_func { struct base_function {
static int call(lua_State* L) { static int call(lua_State* L) {
void** pinheritancedata = static_cast<void**>(stack::get<lightuserdata_t>(L, 1).value); void** pinheritancedata = static_cast<void**>(stack::get<lightuserdata_t>(L, 1).value);
void* inheritancedata = *pinheritancedata; void* inheritancedata = *pinheritancedata;
if (inheritancedata == nullptr) { if (inheritancedata == nullptr) {
throw sol_error("call from Lua to C++ function has null data"); throw sol_error("call from Lua to C++ function has null data");
} }
lua_func* pfx = static_cast<lua_func*>(inheritancedata); base_function* pfx = static_cast<base_function*>(inheritancedata);
lua_func& fx = *pfx; base_function& fx = *pfx;
int r = fx(L); int r = fx(L);
return r; return r;
} }
@ -119,8 +119,8 @@ struct lua_func {
static int gc(lua_State* L) { static int gc(lua_State* L) {
void** puserdata = static_cast<void**>(stack::get<userdata_t>(L, 1).value); void** puserdata = static_cast<void**>(stack::get<userdata_t>(L, 1).value);
void* userdata = *puserdata; void* userdata = *puserdata;
lua_func* ptr = static_cast<lua_func*>(userdata); base_function* ptr = static_cast<base_function*>(userdata);
std::default_delete<lua_func> dx{}; std::default_delete<base_function> dx{};
dx(ptr); dx(ptr);
return 0; return 0;
} }
@ -129,17 +129,17 @@ struct lua_func {
throw sol_error("failure to call specialized wrapped C++ function from Lua"); throw sol_error("failure to call specialized wrapped C++ function from Lua");
} }
virtual ~lua_func() {} virtual ~base_function() {}
}; };
template<typename Function> template<typename Function>
struct functor_lua_func : public lua_func { struct functor_function : public base_function {
typedef decltype(&Function::operator()) function_type; typedef decltype(&Function::operator()) function_type;
typedef function_traits<function_type> traits_type; typedef function_traits<function_type> traits_type;
Function fx; Function fx;
template<typename... FxArgs> template<typename... FxArgs>
functor_lua_func(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {} functor_function(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {}
template<typename... Args> template<typename... Args>
int operator()(types<void>, types<Args...> t, lua_State* L) { int operator()(types<void>, types<Args...> t, lua_State* L) {
@ -165,41 +165,8 @@ struct functor_lua_func : public lua_func {
} }
}; };
template<typename Function, typename T = Function, bool is_member_pointer = std::is_member_function_pointer<Function>::value>
struct function_lua_func : public lua_func {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type;
function_type fx;
template<typename... FxArgs>
function_lua_func(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {}
template<typename... Args>
int operator()(types<void>, types<Args...> t, lua_State* L) {
stack::pop_call(L, fx, t);
return 0;
}
template<typename... Args>
int operator()(types<>, types<Args...> t, lua_State* L) {
return (*this)(types<void>(), t, L);
}
template<typename... Ret, typename... Args>
int operator()(types<Ret...>, types<Args...> t, lua_State* L) {
typedef typename multi_return<Ret...>::type return_type;
return_type r = stack::pop_call(L, fx, t);
stack::push(L, std::move(r));
return sizeof...(Ret);
}
virtual int operator()(lua_State* L) override {
return (*this)(tuple_types<typename traits_type::return_type>(), typename traits_type::args_type(), L);
}
};
template<typename Function, typename T> template<typename Function, typename T>
struct function_lua_func<Function, T, true> : public lua_func { struct member_function : public base_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type; typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type; typedef function_traits<function_type> traits_type;
struct functor { struct functor {
@ -216,7 +183,7 @@ struct function_lua_func<Function, T, true> : public lua_func {
} fx; } fx;
template<typename... FxArgs> template<typename... FxArgs>
function_lua_func(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward<FxArgs>(fxargs)...) {} member_function(T m, FxArgs&&... fxargs): fx(std::move(m), std::forward<FxArgs>(fxargs)...) {}
template<typename... Args> template<typename... Args>
int operator()(types<void>, types<Args...> t, lua_State* L) { int operator()(types<void>, types<Args...> t, lua_State* L) {
@ -243,7 +210,7 @@ struct function_lua_func<Function, T, true> : public lua_func {
}; };
template<typename Function, typename T> template<typename Function, typename T>
struct class_lua_func : public lua_func { struct userdata_function : public base_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type; typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type; typedef function_traits<function_type> traits_type;
struct functor { struct functor {
@ -266,7 +233,7 @@ struct class_lua_func : public lua_func {
} fx; } fx;
template<typename... FxArgs> template<typename... FxArgs>
class_lua_func(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {} userdata_function(FxArgs&&... fxargs): fx(std::forward<FxArgs>(fxargs)...) {}
template<typename... Args> template<typename... Args>
int operator()(types<void>, types<Args...> t, lua_State* L) { int operator()(types<void>, types<Args...> t, lua_State* L) {

View File

@ -50,10 +50,6 @@ public:
lua_rawgeti(L, LUA_REGISTRYINDEX, ref); lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
} }
void pop() const noexcept {
lua_pop(L, 1);
}
reference(reference&& o) noexcept { reference(reference&& o) noexcept {
L = o.L; L = o.L;
ref = o.ref; ref = o.ref;

View File

@ -24,7 +24,7 @@
#include "proxy.hpp" #include "proxy.hpp"
#include "stack.hpp" #include "stack.hpp"
#include "lua_function.hpp" #include "function_types.hpp"
#include "userdata.hpp" #include "userdata.hpp"
namespace sol { namespace sol {
@ -168,6 +168,9 @@ public:
return proxy<const table, T>(*this, std::forward<T>(key)); return proxy<const table, T>(*this, std::forward<T>(key));
} }
void pop(int n = 1) const noexcept {
lua_pop(state(), n);
}
private: private:
template<typename T, typename TFx> template<typename T, typename TFx>
table& set_isfunction_fx(std::true_type, T&& key, TFx&& fx) { table& set_isfunction_fx(std::true_type, T&& key, TFx&& fx) {
@ -192,7 +195,7 @@ private:
template<typename T, typename TFx> template<typename T, typename TFx>
table& set_isconvertible_fx(std::false_type, T&& key, TFx&& fx) { table& set_isconvertible_fx(std::false_type, T&& key, TFx&& fx) {
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx; typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
std::unique_ptr<lua_func> sptr(new functor_lua_func<clean_fx>(std::forward<TFx>(fx))); std::unique_ptr<base_function> sptr(new functor_function<clean_fx>(std::forward<TFx>(fx)));
return set_fx(std::forward<T>(key), std::move(sptr)); return set_fx(std::forward<T>(key), std::move(sptr));
} }
@ -204,7 +207,7 @@ private:
template<typename T, typename TFx, typename TObj> template<typename T, typename TFx, typename TObj>
table& set_lvalue_fx(std::false_type, T&& key, TFx&& fx, TObj&& obj) { table& set_lvalue_fx(std::false_type, T&& key, TFx&& fx, TObj&& obj) {
typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx; typedef typename std::remove_pointer<Decay<TFx>>::type clean_fx;
std::unique_ptr<lua_func> sptr(new function_lua_func<clean_fx, TObj>(std::forward<TObj>(obj), std::forward<TFx>(fx))); std::unique_ptr<base_function> sptr(new member_function<clean_fx, TObj>(std::forward<TObj>(obj), std::forward<TFx>(fx)));
return set_fx(std::forward<T>(key), std::move(sptr)); return set_fx(std::forward<T>(key), std::move(sptr));
} }
@ -219,7 +222,7 @@ private:
// with the same member function pointer type // with the same member function pointer type
Decay<TFx> fxptr(std::forward<TFx>(fx)); Decay<TFx> fxptr(std::forward<TFx>(fx));
void* userobjdata = static_cast<void*>(detail::get_ptr(obj)); void* userobjdata = static_cast<void*>(detail::get_ptr(obj));
lua_CFunction freefunc = &static_object_lua_func<Decay<TObj>, TFx>::call; lua_CFunction freefunc = &static_member_function<Decay<TObj>, TFx>::call;
const char* freefuncname = fkey.c_str(); const char* freefuncname = fkey.c_str();
const luaL_Reg funcreg[2] = { const luaL_Reg funcreg[2] = {
{ freefuncname, freefunc }, { freefuncname, freefunc },
@ -241,7 +244,7 @@ private:
table& set_fx(std::false_type, T&& key, TFx&& fx) { table& set_fx(std::false_type, T&& key, TFx&& fx) {
std::string fkey(key); std::string fkey(key);
Decay<TFx> target(std::forward<TFx>(fx)); Decay<TFx> target(std::forward<TFx>(fx));
lua_CFunction freefunc = &static_lua_func<TFx>::call; lua_CFunction freefunc = &static_function<TFx>::call;
const char* freefuncname = fkey.c_str(); const char* freefuncname = fkey.c_str();
const luaL_Reg funcreg[2] = { const luaL_Reg funcreg[2] = {
{ freefuncname, freefunc }, { freefuncname, freefunc },
@ -257,14 +260,14 @@ private:
} }
template<typename T> template<typename T>
table& set_fx(T&& key, std::unique_ptr<lua_func> luafunc) { table& set_fx(T&& key, std::unique_ptr<base_function> luafunc) {
std::string fkey(key); std::string fkey(key);
std::string metakey("sol.stateful."); std::string metakey("sol.stateful.");
metakey += fkey; metakey += fkey;
metakey += ".meta"; metakey += ".meta";
lua_func* target = luafunc.release(); base_function* target = luafunc.release();
void* userdata = reinterpret_cast<void*>(target); void* userdata = reinterpret_cast<void*>(target);
lua_CFunction freefunc = &lua_func::call; lua_CFunction freefunc = &base_function::call;
const char* freefuncname = fkey.c_str(); const char* freefuncname = fkey.c_str();
const char* metatablename = metakey.c_str(); const char* metatablename = metakey.c_str();
const luaL_Reg funcreg[2] = { const luaL_Reg funcreg[2] = {
@ -274,7 +277,7 @@ private:
if (luaL_newmetatable(state(), metatablename) == 1) { if (luaL_newmetatable(state(), metatablename) == 1) {
lua_pushstring(state(), "__gc"); lua_pushstring(state(), "__gc");
lua_pushcclosure(state(), &lua_func::gc, 0); lua_pushcclosure(state(), &base_function::gc, 0);
lua_settable(state(), -3); lua_settable(state(), -3);
} }

View File

@ -23,7 +23,7 @@
#define SOL_USERDATA_HPP #define SOL_USERDATA_HPP
#include "state.hpp" #include "state.hpp"
#include "lua_function.hpp" #include "function_types.hpp"
#include "demangle.hpp" #include "demangle.hpp"
#include <vector> #include <vector>
@ -44,7 +44,7 @@ private:
std::string luaname; std::string luaname;
std::vector<std::string> functionnames; std::vector<std::string> functionnames;
std::vector<std::unique_ptr<lua_func>> functions; std::vector<std::unique_ptr<base_function>> functions;
std::vector<luaL_Reg> functiontable; std::vector<luaL_Reg> functiontable;
std::vector<luaL_Reg> metatable; std::vector<luaL_Reg> metatable;
@ -128,8 +128,8 @@ private:
void* inheritancedata = stack::get<lightuserdata_t>(L, i + 1); void* inheritancedata = stack::get<lightuserdata_t>(L, i + 1);
if (inheritancedata == nullptr) if (inheritancedata == nullptr)
throw sol_error("call from Lua to C++ function has null data"); throw sol_error("call from Lua to C++ function has null data");
lua_func* pfx = static_cast<lua_func*>(inheritancedata); base_function* pfx = static_cast<base_function*>(inheritancedata);
lua_func& fx = *pfx; base_function& fx = *pfx;
int r = fx(L); int r = fx(L);
return r; return r;
} }
@ -144,7 +144,7 @@ private:
void build_function_tables(Ret(T::* func)(MArgs...), std::string name, Args&&... args) { void build_function_tables(Ret(T::* func)(MArgs...), std::string name, Args&&... args) {
typedef typename std::decay<decltype(func)>::type fx_t; typedef typename std::decay<decltype(func)>::type fx_t;
functionnames.push_back(std::move(name)); functionnames.push_back(std::move(name));
functions.emplace_back(detail::make_unique<class_lua_func<fx_t, T>>(std::move(func))); functions.emplace_back(detail::make_unique<userdata_function<fx_t, T>>(std::move(func)));
functiontable.push_back({ functionnames.back().c_str(), &class_func<n>::call }); functiontable.push_back({ functionnames.back().c_str(), &class_func<n>::call });
build_function_tables<n + 1>(std::forward<Args>(args)...); build_function_tables<n + 1>(std::forward<Args>(args)...);
} }

View File

@ -17,23 +17,23 @@ struct object {
}; };
struct fuser { struct fuser {
int x; int x;
fuser( ) : x( 0 ) { fuser( ) : x( 0 ) {
} }
fuser( int x ) : x( x ) { fuser( int x ) : x( x ) {
} }
int add( int y ) { int add( int y ) {
return x + y; return x + y;
} }
int add2( int y ) { int add2( int y ) {
return x + y + 2; return x + y + 2;
} }
}; };
int plop_xyz(int x, int y, std::string z) { int plop_xyz(int x, int y, std::string z) {
@ -345,30 +345,29 @@ TEST_CASE("tables/operator[]", "Check if operator[] retrieval and setting works
REQUIRE_NOTHROW(assert1(lua.global_table())); REQUIRE_NOTHROW(assert1(lua.global_table()));
} }
TEST_CASE( "tables/userdata", "Show that we can create classes from userdata and use them" ) { TEST_CASE("tables/userdata", "Show that we can create classes from userdata and use them") {
sol::state lua; sol::state lua;
sol::userdata<fuser> lc{ &fuser::add, "add", &fuser::add2, "add2" }; sol::userdata<fuser> lc{ &fuser::add, "add", &fuser::add2, "add2" };
lua.set_class( lc ); lua.set_class( lc );
lua.script( "a = fuser:new()\n" lua.script("a = fuser:new()\n"
"b = a:add(1)\n" "b = a:add(1)\n"
"c = a:add2(1)\n" "c = a:add2(1)\n");
"\n" );
sol::object a = lua.get<sol::object>( "a" ); sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>( "b" ); sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>( "c" ); sol::object c = lua.get<sol::object>("c");
REQUIRE( ( a.is<sol::table>( ) ) ); REQUIRE((a.is<sol::table>()));
auto atype = a.get_type( ); auto atype = a.get_type();
auto btype = b.get_type( ); auto btype = b.get_type();
auto ctype = c.get_type( ); auto ctype = c.get_type();
REQUIRE( ( atype == sol::type::table ) ); REQUIRE((atype == sol::type::table));
REQUIRE( ( btype == sol::type::number ) ); REQUIRE((btype == sol::type::number));
REQUIRE( ( ctype == sol::type::number ) ); REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>( ); int bresult = b.as<int>();
int cresult = c.as<int>( ); int cresult = c.as<int>();
REQUIRE( bresult == 1 ); REQUIRE(bresult == 1);
REQUIRE( cresult == 3 ); REQUIRE(cresult == 3);
} }