mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
sol::var is now in business
This commit is contained in:
parent
0dcc879ce6
commit
dc05552e81
|
@ -11,4 +11,5 @@ This type is no different from :doc:`regular usertype<usertype>`, but with the f
|
||||||
- :doc:`properties<property>` also become functions, similar to how member variables are treated above
|
- :doc:`properties<property>` also become functions, similar to how member variables are treated above
|
||||||
* Automatic "__index" and "__newindex" handling is not done
|
* Automatic "__index" and "__newindex" handling is not done
|
||||||
- Overriding either of these properties leaves it entirely up to you to handle how you find variables
|
- Overriding either of these properties leaves it entirely up to you to handle how you find variables
|
||||||
|
- This includes ``sol::var( ... )``, and similar "dot-access" types
|
||||||
- If you override "__index" or "__newindex", you must perform a raw get on the original table and return a valid function / value if you want it to find the members you already set on the ``simple_usertype``
|
- If you override "__index" or "__newindex", you must perform a raw get on the original table and return a valid function / value if you want it to find the members you already set on the ``simple_usertype``
|
||||||
|
|
|
@ -226,6 +226,10 @@ Then, to register the base classes explicitly:
|
||||||
sol::base_classes, sol::bases<A>()
|
sol::base_classes, sol::bases<A>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
You must list ALL base classes, including (if there were any) the base classes of A, and the base classes of those base classes, etc. if you want Sol/Lua to handle them automagically.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Sol does not support down-casting from a base class to a derived class at runtime.
|
Sol does not support down-casting from a base class to a derived class at runtime.
|
||||||
|
|
16
sol/call.hpp
16
sol/call.hpp
|
@ -170,6 +170,20 @@ namespace sol {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, bool is_index, bool is_variable, bool checked, int boost, typename C>
|
||||||
|
struct agnostic_lua_call_wrapper<var_wrapper<T>, is_index, is_variable, checked, boost, C> {
|
||||||
|
template <typename F>
|
||||||
|
static int call(lua_State* L, F&& f) {
|
||||||
|
if (is_index) {
|
||||||
|
return stack::push(L, detail::unwrap(f.value));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
detail::unwrap(f.value) = stack::get<meta::unwrapped_t<T>>(L, 3 + boost);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
|
template <bool is_index, bool is_variable, bool checked, int boost, typename C>
|
||||||
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> {
|
struct agnostic_lua_call_wrapper<lua_r_CFunction, is_index, is_variable, checked, boost, C> {
|
||||||
static int call(lua_State* L, lua_r_CFunction f) {
|
static int call(lua_State* L, lua_r_CFunction f) {
|
||||||
|
@ -468,6 +482,8 @@ namespace sol {
|
||||||
template <typename R, typename W>
|
template <typename R, typename W>
|
||||||
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
struct is_var_bind<property_wrapper<R, W>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_var_bind<var_wrapper<T>> : std::true_type {};
|
||||||
} // call_detail
|
} // call_detail
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -196,9 +196,12 @@ namespace sol {
|
||||||
return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
|
return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename FP>
|
static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
|
||||||
static int push(lua_State* L, FP&& fp) {
|
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, fp);
|
||||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<FP>(fp));
|
}
|
||||||
|
|
||||||
|
static int push(lua_State* L, function_arguments<T, Args...>&& fp) {
|
||||||
|
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::move(fp));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -75,11 +75,28 @@ namespace sol {
|
||||||
|
|
||||||
// Allow someone to make a member variable readonly (const)
|
// Allow someone to make a member variable readonly (const)
|
||||||
template <typename R, typename T>
|
template <typename R, typename T>
|
||||||
auto readonly(R T::* v) {
|
inline auto readonly(R T::* v) {
|
||||||
typedef const R C;
|
typedef const R C;
|
||||||
return static_cast<C T::*>(v);
|
return static_cast<C T::*>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct var_wrapper {
|
||||||
|
T value;
|
||||||
|
template <typename... Args>
|
||||||
|
var_wrapper(Args&&... args) : value(std::forward<Args>(args)...) {}
|
||||||
|
var_wrapper(const var_wrapper&) = default;
|
||||||
|
var_wrapper(var_wrapper&&) = default;
|
||||||
|
var_wrapper& operator=(const var_wrapper&) = default;
|
||||||
|
var_wrapper& operator=(var_wrapper&&) = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
inline auto var(V&& v) {
|
||||||
|
typedef meta::unqualified_t<V> T;
|
||||||
|
return var_wrapper<T>(std::forward<V>(v));
|
||||||
|
}
|
||||||
|
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
#endif // SOL_PROPERTY_HPP
|
#endif // SOL_PROPERTY_HPP
|
||||||
|
|
|
@ -197,6 +197,9 @@ namespace sol {
|
||||||
|
|
||||||
template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>>
|
template <std::size_t Idx, typename N, typename F, typename = std::enable_if_t<!meta::any_same<meta::unqualified_t<N>, base_classes_tag, call_construction>::value>>
|
||||||
void make_regs(regs_t& l, int& index, N&& n, F&&) {
|
void make_regs(regs_t& l, int& index, N&& n, F&&) {
|
||||||
|
if (is_variable_binding<meta::unqualified_t<F>>::value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>());
|
luaL_Reg reg = usertype_detail::make_reg(std::forward<N>(n), make_func<Idx>());
|
||||||
// Returnable scope
|
// Returnable scope
|
||||||
// That would be a neat keyword for C++
|
// That would be a neat keyword for C++
|
||||||
|
@ -223,7 +226,7 @@ namespace sol {
|
||||||
usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...),
|
usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...),
|
||||||
indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>),
|
indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>),
|
||||||
destructfunc(nullptr), callconstructfunc(nullptr), baseclasscheck(nullptr), baseclasscast(nullptr),
|
destructfunc(nullptr), callconstructfunc(nullptr), baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||||
mustindex(contains_variable() || contains_index()), secondarymeta(false) {
|
mustindex(contains_variable() || contains_index()), secondarymeta(contains_variable()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t I0, std::size_t I1, bool is_index>
|
template <std::size_t I0, std::size_t I1, bool is_index>
|
||||||
|
@ -400,7 +403,11 @@ namespace sol {
|
||||||
lua_createtable(L, 0, 1);
|
lua_createtable(L, 0, 1);
|
||||||
stack_reference metabehind(L, -1);
|
stack_reference metabehind(L, -1);
|
||||||
if (um.callconstructfunc != nullptr) {
|
if (um.callconstructfunc != nullptr) {
|
||||||
stack::set_field(L, sol::meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
stack::set_field(L, meta_function::call_function, make_closure(um.callconstructfunc, make_light(um)), metabehind.stack_index());
|
||||||
|
}
|
||||||
|
if (um.secondarymeta) {
|
||||||
|
stack::set_field(L, meta_function::index, make_closure(umt_t::index_call, make_light(um)), metabehind.stack_index());
|
||||||
|
stack::set_field(L, meta_function::new_index, make_closure(umt_t::new_index_call, make_light(um)), metabehind.stack_index());
|
||||||
}
|
}
|
||||||
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
stack::set_field(L, metatable_key, metabehind, t.stack_index());
|
||||||
metabehind.pop();
|
metabehind.pop();
|
||||||
|
|
|
@ -1191,3 +1191,58 @@ end
|
||||||
lua["func"](bar);
|
lua["func"](bar);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("usertype/vars", "usertype vars can bind various class items") {
|
||||||
|
static int muh_variable = 25;
|
||||||
|
static int through_variable = 10;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
struct test {};
|
||||||
|
lua.new_usertype<test>("test",
|
||||||
|
"straight", sol::var(2),
|
||||||
|
"global", sol::var(muh_variable),
|
||||||
|
"ref_global", sol::var(std::ref(muh_variable)),
|
||||||
|
"global2", sol::var(through_variable),
|
||||||
|
"ref_global2", sol::var(std::ref(through_variable))
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
t = test.new()
|
||||||
|
print(t.global)
|
||||||
|
t.global = 50
|
||||||
|
print(t.global)
|
||||||
|
)");
|
||||||
|
int mv = lua["test"]["global"];
|
||||||
|
REQUIRE(mv == 50);
|
||||||
|
REQUIRE(muh_variable == 25);
|
||||||
|
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
print(t.ref_global)
|
||||||
|
t.ref_global = 50
|
||||||
|
print(t.ref_global)
|
||||||
|
)");
|
||||||
|
int rmv = lua["test"]["ref_global"];
|
||||||
|
REQUIRE(rmv == 50);
|
||||||
|
REQUIRE(muh_variable == 50);
|
||||||
|
|
||||||
|
REQUIRE(through_variable == 10);
|
||||||
|
lua.script(R"(
|
||||||
|
print(test.global2)
|
||||||
|
test.global2 = 35
|
||||||
|
print(test.global2)
|
||||||
|
)");
|
||||||
|
int tv = lua["test"]["global2"];
|
||||||
|
REQUIRE(through_variable == 10);
|
||||||
|
REQUIRE(tv == 35);
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
print(test.ref_global2)
|
||||||
|
test.ref_global2 = 35
|
||||||
|
print(test.ref_global2)
|
||||||
|
)");
|
||||||
|
int rtv = lua["test"]["ref_global2"];
|
||||||
|
REQUIRE(rtv == 35);
|
||||||
|
REQUIRE(through_variable == 35);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user