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
|
||||
* 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
|
||||
- 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``
|
||||
|
|
|
@ -226,6 +226,10 @@ Then, to register the base classes explicitly:
|
|||
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::
|
||||
|
||||
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>
|
||||
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) {
|
||||
|
@ -468,6 +482,8 @@ namespace sol {
|
|||
template <typename R, typename W>
|
||||
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
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -196,9 +196,12 @@ namespace sol {
|
|||
return stack::push<T>(L, detail::forward_get<I>(fp.params)...);
|
||||
}
|
||||
|
||||
template <typename FP>
|
||||
static int push(lua_State* L, FP&& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, std::forward<FP>(fp));
|
||||
static int push(lua_State* L, const function_arguments<T, Args...>& fp) {
|
||||
return push_func(std::make_index_sequence<sizeof...(Args)>(), L, 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)
|
||||
template <typename R, typename T>
|
||||
auto readonly(R T::* v) {
|
||||
inline auto readonly(R T::* v) {
|
||||
typedef const R C;
|
||||
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
|
||||
|
||||
#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>>
|
||||
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>());
|
||||
// Returnable scope
|
||||
// That would be a neat keyword for C++
|
||||
|
@ -223,7 +226,7 @@ namespace sol {
|
|||
usertype_metatable(Args&&... args) : functions(std::forward<Args>(args)...),
|
||||
indexfunc(usertype_detail::indexing_fail<true>), newindexfunc(usertype_detail::indexing_fail<false>),
|
||||
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>
|
||||
|
@ -400,7 +403,11 @@ namespace sol {
|
|||
lua_createtable(L, 0, 1);
|
||||
stack_reference metabehind(L, -1);
|
||||
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());
|
||||
metabehind.pop();
|
||||
|
|
|
@ -1191,3 +1191,58 @@ end
|
|||
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