mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Merge remote-tracking branch 'root/classes'
This commit is contained in:
commit
4d6d39be88
|
@ -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) {
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)...);
|
||||||
}
|
}
|
||||||
|
|
35
tests.cpp
35
tests.cpp
|
@ -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);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user