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 {
template<typename Function>
struct static_lua_func {
struct static_function {
typedef typename std::remove_pointer<typename std::decay<Function>::type>::type function_type;
typedef function_traits<function_type> traits_type;
@ -64,7 +64,7 @@ struct static_lua_func {
};
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 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) {
void** pinheritancedata = static_cast<void**>(stack::get<lightuserdata_t>(L, 1).value);
void* inheritancedata = *pinheritancedata;
if (inheritancedata == nullptr) {
throw sol_error("call from Lua to C++ function has null data");
}
lua_func* pfx = static_cast<lua_func*>(inheritancedata);
lua_func& fx = *pfx;
base_function* pfx = static_cast<base_function*>(inheritancedata);
base_function& fx = *pfx;
int r = fx(L);
return r;
}
@ -119,8 +119,8 @@ struct lua_func {
static int gc(lua_State* L) {
void** puserdata = static_cast<void**>(stack::get<userdata_t>(L, 1).value);
void* userdata = *puserdata;
lua_func* ptr = static_cast<lua_func*>(userdata);
std::default_delete<lua_func> dx{};
base_function* ptr = static_cast<base_function*>(userdata);
std::default_delete<base_function> dx{};
dx(ptr);
return 0;
}
@ -129,17 +129,17 @@ struct lua_func {
throw sol_error("failure to call specialized wrapped C++ function from Lua");
}
virtual ~lua_func() {}
virtual ~base_function() {}
};
template<typename Function>
struct functor_lua_func : public lua_func {
struct functor_function : public base_function {
typedef decltype(&Function::operator()) function_type;
typedef function_traits<function_type> traits_type;
Function fx;
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>
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>
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 function_traits<function_type> traits_type;
struct functor {
@ -216,7 +183,7 @@ struct function_lua_func<Function, T, true> : public lua_func {
} fx;
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>
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>
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 function_traits<function_type> traits_type;
struct functor {
@ -266,7 +233,7 @@ struct class_lua_func : public lua_func {
} fx;
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>
int operator()(types<void>, types<Args...> t, lua_State* L) {

View File

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

View File

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

View File

@ -23,7 +23,7 @@
#define SOL_USERDATA_HPP
#include "state.hpp"
#include "lua_function.hpp"
#include "function_types.hpp"
#include "demangle.hpp"
#include <vector>
@ -44,7 +44,7 @@ private:
std::string luaname;
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> metatable;
@ -128,8 +128,8 @@ private:
void* inheritancedata = stack::get<lightuserdata_t>(L, i + 1);
if (inheritancedata == nullptr)
throw sol_error("call from Lua to C++ function has null data");
lua_func* pfx = static_cast<lua_func*>(inheritancedata);
lua_func& fx = *pfx;
base_function* pfx = static_cast<base_function*>(inheritancedata);
base_function& fx = *pfx;
int r = fx(L);
return r;
}
@ -144,7 +144,7 @@ private:
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(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 });
build_function_tables<n + 1>(std::forward<Args>(args)...);
}

View File

@ -17,23 +17,23 @@ struct object {
};
struct fuser {
int x;
fuser( ) : x( 0 ) {
}
fuser( int x ) : x( x ) {
}
int x;
fuser( ) : x( 0 ) {
}
fuser( int x ) : x( x ) {
}
int add( int y ) {
return x + y;
}
int add2( int y ) {
return x + y + 2;
}
int add( int y ) {
return x + y;
}
int add2( int y ) {
return x + y + 2;
}
};
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()));
}
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" };
lua.set_class( lc );
sol::userdata<fuser> lc{ &fuser::add, "add", &fuser::add2, "add2" };
lua.set_class( lc );
lua.script( "a = fuser:new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n"
"\n" );
lua.script("a = fuser:new()\n"
"b = a:add(1)\n"
"c = a:add2(1)\n");
sol::object a = lua.get<sol::object>( "a" );
sol::object b = lua.get<sol::object>( "b" );
sol::object c = lua.get<sol::object>( "c" );
REQUIRE( ( a.is<sol::table>( ) ) );
auto atype = a.get_type( );
auto btype = b.get_type( );
auto ctype = c.get_type( );
REQUIRE( ( atype == sol::type::table ) );
REQUIRE( ( btype == sol::type::number ) );
REQUIRE( ( ctype == sol::type::number ) );
int bresult = b.as<int>( );
int cresult = c.as<int>( );
REQUIRE( bresult == 1 );
REQUIRE( cresult == 3 );
sol::object a = lua.get<sol::object>("a");
sol::object b = lua.get<sol::object>("b");
sol::object c = lua.get<sol::object>("c");
REQUIRE((a.is<sol::table>()));
auto atype = a.get_type();
auto btype = b.get_type();
auto ctype = c.get_type();
REQUIRE((atype == sol::type::table));
REQUIRE((btype == sol::type::number));
REQUIRE((ctype == sol::type::number));
int bresult = b.as<int>();
int cresult = c.as<int>();
REQUIRE(bresult == 1);
REQUIRE(cresult == 3);
}