mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
OoOoOooh and the world exploooodes.
Added new examples to illustrate a few things people were wondering about HEAVILY fixed up usertypes and inheritance. Again. Sigh. One day it'll all be correct.
This commit is contained in:
parent
8028628868
commit
330df79ab9
|
@ -43,13 +43,21 @@ running lua code
|
||||||
// load and execute from file
|
// load and execute from file
|
||||||
lua.script_file("path/to/luascript.lua");
|
lua.script_file("path/to/luascript.lua");
|
||||||
|
|
||||||
|
// run a script, get the result
|
||||||
|
int value = lua.script("return 54");
|
||||||
|
// value == 54
|
||||||
|
|
||||||
// load file without execute
|
// load file without execute
|
||||||
sol::load_result script1 = state.load_file("path/to/luascript.lua");
|
sol::load_result script1 = lua.load_file("path/to/luascript.lua");
|
||||||
script1(); //execute
|
script1(); //execute
|
||||||
// load string without execute
|
// load string without execute
|
||||||
sol::load_result script2 = state.load("a = 'test'");
|
sol::load_result script2 = lua.load("a = 'test'");
|
||||||
script2(); //execute
|
script2(); //execute
|
||||||
|
|
||||||
|
sol::load_result script3 = lua.load("return 24");
|
||||||
|
int value2 = script3(); // execute, get return value
|
||||||
|
// value2 == 24
|
||||||
|
|
||||||
|
|
||||||
set and get variables
|
set and get variables
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -347,6 +355,40 @@ The lua code to call these things is:
|
||||||
Can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it.
|
Can use ``sol::readonly( &some_class::variable )`` to make a variable readonly and error if someone tries to write to it.
|
||||||
|
|
||||||
|
|
||||||
|
self call
|
||||||
|
---------
|
||||||
|
|
||||||
|
You can pass the 'self' argument through C++ to emulate 'member function' calls in Lua.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table);
|
||||||
|
|
||||||
|
// a small script using 'self' syntax
|
||||||
|
lua.script(R"(
|
||||||
|
some_table = { some_val = 100 }
|
||||||
|
|
||||||
|
function some_table:add_to_some_val(value)
|
||||||
|
self.some_val = self.some_val + value
|
||||||
|
end
|
||||||
|
|
||||||
|
function print_some_val()
|
||||||
|
print("some_table.some_val = " .. some_table.some_val)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
// do some printing
|
||||||
|
lua["print_some_val"]();
|
||||||
|
// 100
|
||||||
|
|
||||||
|
sol::table self = lua["some_table"];
|
||||||
|
self["add_to_some_val"](self, 10);
|
||||||
|
lua["print_some_val"]();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
multiple returns from lua
|
multiple returns from lua
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
|
47
examples/require.cpp
Normal file
47
examples/require.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS
|
||||||
|
#include <sol.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct some_class {
|
||||||
|
int bark = 2012;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::table open_mylib(sol::this_state s) {
|
||||||
|
sol::state_view lua(s);
|
||||||
|
|
||||||
|
sol::table module = lua.create_table();
|
||||||
|
module["func"] = []() { /* super cool function here */ };
|
||||||
|
// register a class too
|
||||||
|
module.new_usertype<some_class>("some_class",
|
||||||
|
"bark", &some_class::bark
|
||||||
|
);
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== require example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::package);
|
||||||
|
// sol::c_call takes functions at the template level
|
||||||
|
// and turns it into a lua_CFunction
|
||||||
|
// alternatively, one can use sol::c_call<sol::wrap<callable_struct, callable_struct{}>> to make the call
|
||||||
|
// if it's a constexpr struct
|
||||||
|
lua.require("my_lib", sol::c_call<decltype(&open_mylib), &open_mylib>);
|
||||||
|
|
||||||
|
// do ALL THE THINGS YOU LIKE
|
||||||
|
lua.script(R"(
|
||||||
|
s = my_lib.some_class.new()
|
||||||
|
s.bark = 20;
|
||||||
|
)");
|
||||||
|
some_class& s = lua["s"];
|
||||||
|
assert(s.bark == 20);
|
||||||
|
std::cout << "s.bark = " << s.bark << std::endl;
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
35
examples/self_call.cpp
Normal file
35
examples/self_call.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS
|
||||||
|
#include <sol.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== self_call example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::table);
|
||||||
|
|
||||||
|
// a small script using 'self' syntax
|
||||||
|
lua.script(R"(
|
||||||
|
some_table = { some_val = 100 }
|
||||||
|
|
||||||
|
function some_table:add_to_some_val(value)
|
||||||
|
self.some_val = self.some_val + value
|
||||||
|
end
|
||||||
|
|
||||||
|
function print_some_val()
|
||||||
|
print("some_table.some_val = " .. some_table.some_val)
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
// do some printing
|
||||||
|
lua["print_some_val"]();
|
||||||
|
// 100
|
||||||
|
|
||||||
|
sol::table self = lua["some_table"];
|
||||||
|
self["add_to_some_val"](self, 10);
|
||||||
|
lua["print_some_val"]();
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
|
@ -58,12 +58,12 @@ namespace sol {
|
||||||
const std::size_t id_for<T>::value = unique_id();
|
const std::size_t id_for<T>::value = unique_id();
|
||||||
|
|
||||||
inline decltype(auto) base_class_check_key() {
|
inline decltype(auto) base_class_check_key() {
|
||||||
static const auto& key = u8"♡o。.(✿ฺ。 ✿ฺ)";
|
static const auto& key = "class_check";
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline decltype(auto) base_class_cast_key() {
|
inline decltype(auto) base_class_cast_key() {
|
||||||
static const auto& key = u8"(◕‿◕✿)";
|
static const auto& key = "class_cast";
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,11 +85,11 @@ namespace sol {
|
||||||
|
|
||||||
template <typename Base, typename... Args>
|
template <typename Base, typename... Args>
|
||||||
static bool type_check_bases(types<Base, Args...>, std::size_t ti) {
|
static bool type_check_bases(types<Base, Args...>, std::size_t ti) {
|
||||||
return ti != id_for<Base>::value || type_check_bases(types<Args...>(), ti);
|
return ti == id_for<Base>::value || type_check_bases(types<Args...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool type_check(std::size_t ti) {
|
static bool type_check(std::size_t ti) {
|
||||||
return ti != id_for<T>::value || type_check_bases(types<Bases...>(), ti);
|
return ti == id_for<T>::value || type_check_bases(types<Bases...>(), ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* type_cast_bases(types<>, T*, std::size_t) {
|
static void* type_cast_bases(types<>, T*, std::size_t) {
|
||||||
|
|
|
@ -161,18 +161,30 @@ namespace sol {
|
||||||
bool mustindex;
|
bool mustindex;
|
||||||
bool secondarymeta;
|
bool secondarymeta;
|
||||||
|
|
||||||
|
template <typename N>
|
||||||
|
void insert(N&& n, object&& o) {
|
||||||
|
std::string key = usertype_detail::make_string(std::forward<N>(n));
|
||||||
|
auto hint = registrations.find(key);
|
||||||
|
if (hint == registrations.cend()) {
|
||||||
|
registrations.emplace_hint(hint, std::move(key), std::move(o));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hint->second = std::move(o);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
template <typename N, typename F, meta::enable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
void add_function(lua_State* L, N&& n, F&& f) {
|
void add_function(lua_State* L, N&& n, F&& f) {
|
||||||
registrations.emplace(usertype_detail::make_string(std::forward<N>(n)), make_object(L, as_function_reference(std::forward<F>(f))));
|
insert(std::forward<N>(n), make_object(L, as_function_reference(std::forward<F>(f))));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
template <typename N, typename F, meta::disable<meta::is_callable<meta::unwrap_unqualified_t<F>>> = meta::enabler>
|
||||||
void add_function(lua_State* L, N&& n, F&& f) {
|
void add_function(lua_State* L, N&& n, F&& f) {
|
||||||
|
object o = make_object(L, std::forward<F>(f));
|
||||||
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||||
callconstructfunc = make_object(L, std::forward<F>(f));
|
callconstructfunc = std::move(o);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
registrations.emplace(usertype_detail::make_string(std::forward<N>(n)), make_object(L, std::forward<F>(f)));
|
insert(std::forward<N>(n), std::move(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
template <typename N, typename F, meta::disable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
||||||
|
@ -182,9 +194,16 @@ namespace sol {
|
||||||
|
|
||||||
template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
||||||
void add(lua_State*, N&& n, F&& f) {
|
void add(lua_State*, N&& n, F&& f) {
|
||||||
varmap.emplace(usertype_detail::make_string(std::forward<N>(n)), std::make_unique<usertype_detail::callable_binding<T, std::decay_t<F>>>(std::forward<F>(f)));
|
|
||||||
mustindex = true;
|
mustindex = true;
|
||||||
secondarymeta = true;
|
secondarymeta = true;
|
||||||
|
std::string key = usertype_detail::make_string(std::forward<N>(n));
|
||||||
|
auto o = std::make_unique<usertype_detail::callable_binding<T, std::decay_t<F>>>(std::forward<F>(f));
|
||||||
|
auto hint = varmap.find(key);
|
||||||
|
if (hint == varmap.cend()) {
|
||||||
|
varmap.emplace_hint(hint, std::move(key), std::move(o));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hint->second = std::move(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename... Fxs>
|
template <typename N, typename... Fxs>
|
||||||
|
@ -194,7 +213,7 @@ namespace sol {
|
||||||
callconstructfunc = std::move(o);
|
callconstructfunc = std::move(o);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
registrations.emplace(usertype_detail::make_string(std::forward<N>(n)), std::move(o));
|
insert(std::forward<N>(n), std::move(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename N, typename... Lists>
|
template <typename N, typename... Lists>
|
||||||
|
@ -204,7 +223,27 @@ namespace sol {
|
||||||
callconstructfunc = std::move(o);
|
callconstructfunc = std::move(o);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
registrations.emplace(usertype_detail::make_string(std::forward<N>(n)), std::move(o));
|
insert(std::forward<N>(n), std::move(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename N>
|
||||||
|
void add(lua_State* L, N&& n, destructor_wrapper<void> c) {
|
||||||
|
object o(L, in_place<detail::tagged<T, destructor_wrapper<void>>>, std::move(c));
|
||||||
|
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||||
|
callconstructfunc = std::move(o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
insert(std::forward<N>(n), std::move(o));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename N, typename Fx>
|
||||||
|
void add(lua_State* L, N&& n, destructor_wrapper<Fx> c) {
|
||||||
|
object o(L, in_place<detail::tagged<T, destructor_wrapper<Fx>>>, std::move(c));
|
||||||
|
if (std::is_same<meta::unqualified_t<N>, call_construction>::value) {
|
||||||
|
callconstructfunc = std::move(o);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
insert(std::forward<N>(n), std::move(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Bases>
|
template <typename... Bases>
|
||||||
|
@ -224,6 +263,7 @@ namespace sol {
|
||||||
newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>;
|
newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
template<std::size_t... I, typename Tuple>
|
template<std::size_t... I, typename Tuple>
|
||||||
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
|
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
|
||||||
: callconstructfunc(nil),
|
: callconstructfunc(nil),
|
||||||
|
@ -237,7 +277,6 @@ namespace sol {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
|
simple_usertype_metatable(lua_State* L, usertype_detail::verified_tag v, Args&&... args) : simple_usertype_metatable(v, std::make_index_sequence<sizeof...(Args) / 2>(), L, std::forward_as_tuple(std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
|
|
|
@ -262,16 +262,18 @@ namespace sol {
|
||||||
if (lua_getmetatable(L, index) == 0) {
|
if (lua_getmetatable(L, index) == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stack_detail::check_metatable<U>(L))
|
int metatableindex = lua_gettop(L);
|
||||||
|
if (stack_detail::check_metatable<U>(L, metatableindex))
|
||||||
return true;
|
return true;
|
||||||
if (stack_detail::check_metatable<U*>(L))
|
if (stack_detail::check_metatable<U*>(L, metatableindex))
|
||||||
return true;
|
return true;
|
||||||
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L))
|
if (stack_detail::check_metatable<detail::unique_usertype<U>>(L, metatableindex))
|
||||||
return true;
|
return true;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
if (detail::has_derived<T>::value) {
|
if (detail::has_derived<T>::value) {
|
||||||
auto pn = stack::pop_n(L, 1);
|
auto pn = stack::pop_n(L, 1);
|
||||||
lua_getfield(L, -1, &detail::base_class_check_key()[0]);
|
lua_pushstring(L, &detail::base_class_check_key()[0]);
|
||||||
|
lua_rawget(L, metatableindex);
|
||||||
if (type_of(L, -1) != type::nil) {
|
if (type_of(L, -1) != type::nil) {
|
||||||
void* basecastdata = lua_touserdata(L, -1);
|
void* basecastdata = lua_touserdata(L, -1);
|
||||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace sol {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class usertype {
|
class usertype {
|
||||||
protected:
|
private:
|
||||||
std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister;
|
std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister;
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -58,6 +58,10 @@ namespace sol {
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter<simple_usertype_metatable<T>, detail::deleter>(L, std::forward<Args>(args)...)) {}
|
usertype(simple_tag, lua_State* L, Args&&... args) : metatableregister(detail::make_unique_deleter<simple_usertype_metatable<T>, detail::deleter>(L, std::forward<Args>(args)...)) {}
|
||||||
|
|
||||||
|
usertype_detail::registrar* registrar_data() {
|
||||||
|
return metatableregister.get();
|
||||||
|
}
|
||||||
|
|
||||||
int push(lua_State* L) {
|
int push(lua_State* L) {
|
||||||
return metatableregister->push_um(L);
|
return metatableregister->push_um(L);
|
||||||
}
|
}
|
||||||
|
@ -65,16 +69,17 @@ namespace sol {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class simple_usertype : public usertype<T> {
|
class simple_usertype : public usertype<T> {
|
||||||
protected:
|
private:
|
||||||
|
typedef usertype<T> base_t;
|
||||||
lua_State* state;
|
lua_State* state;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
simple_usertype(lua_State* L, Args&&... args) : state(L), usertype(simple, L, std::forward<Args>(args)...) {}
|
simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward<Args>(args)...), state(L) {}
|
||||||
|
|
||||||
template <typename N, typename F>
|
template <typename N, typename F>
|
||||||
void add(N&& n, F&& f) {
|
void set(N&& n, F&& f) {
|
||||||
auto meta = (simple_usertype_metatable<T>*) metatableregister.get();
|
auto meta = static_cast<simple_usertype_metatable<T>*>(base_t::registrar_data());
|
||||||
meta->add(state, n, f);
|
meta->add(state, n, f);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -107,13 +107,13 @@ namespace sol {
|
||||||
auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2);
|
auto maybeaccessor = stack::get<optional<string_detail::string_shim>>(L, is_index ? -1 : -2);
|
||||||
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
|
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
|
||||||
if (is_index)
|
if (is_index)
|
||||||
return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data());
|
return luaL_error(L, "sol: attempt to index (get) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str());
|
||||||
else
|
else
|
||||||
return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.data());
|
return luaL_error(L, "sol: attempt to index (set) nil value \"%s\" on userdata (bad (misspelled?) key name or does not exist)", accessor.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool is_index, typename Base>
|
template <bool is_index, typename Base>
|
||||||
static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim& accessor) {
|
static void walk_single_base(lua_State* L, bool& found, int& ret, string_detail::string_shim&) {
|
||||||
if (found)
|
if (found)
|
||||||
return;
|
return;
|
||||||
const char* metakey = &usertype_traits<Base>::metatable[0];
|
const char* metakey = &usertype_traits<Base>::metatable[0];
|
||||||
|
|
247
test_inheritance.cpp
Normal file
247
test_inheritance.cpp
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
#include <catch.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
TEST_CASE("inheritance/basic", "test that metatables are properly inherited") {
|
||||||
|
struct A {
|
||||||
|
int a = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
int b() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C : B, A {
|
||||||
|
double c = 2.4;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D : C {
|
||||||
|
bool d() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.new_usertype<A>("A",
|
||||||
|
"a", &A::a
|
||||||
|
);
|
||||||
|
lua.new_usertype<B>("B",
|
||||||
|
"b", &B::b
|
||||||
|
);
|
||||||
|
lua.new_usertype<C>("C",
|
||||||
|
"c", &C::c,
|
||||||
|
sol::base_classes, sol::bases<B, A>()
|
||||||
|
);
|
||||||
|
lua.new_usertype<D>("D",
|
||||||
|
"d", &D::d,
|
||||||
|
sol::base_classes, sol::bases<C, B, A>()
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.script("obj = D.new()");
|
||||||
|
lua.script("d = obj:d()");
|
||||||
|
bool d = lua["d"];
|
||||||
|
lua.script("c = obj.c");
|
||||||
|
double c = lua["c"];
|
||||||
|
lua.script("b = obj:b()");
|
||||||
|
int b = lua["b"];
|
||||||
|
lua.script("a = obj.a");
|
||||||
|
int a = lua["a"];
|
||||||
|
|
||||||
|
REQUIRE(d);
|
||||||
|
REQUIRE(c == 2.4);
|
||||||
|
REQUIRE(b == 10);
|
||||||
|
REQUIRE(a == 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("inheritance/multi-base", "test that multiple bases all work and overloading for constructors works with them") {
|
||||||
|
class TestClass00 {
|
||||||
|
public:
|
||||||
|
int Thing() const { return 123; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass01 : public TestClass00 {
|
||||||
|
public:
|
||||||
|
TestClass01() : a(1) {}
|
||||||
|
TestClass01(const TestClass00& other) : a(other.Thing()) {}
|
||||||
|
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass02 : public TestClass01 {
|
||||||
|
public:
|
||||||
|
TestClass02() : b(2) {}
|
||||||
|
TestClass02(const TestClass01& other) : b(other.a) {}
|
||||||
|
TestClass02(const TestClass00& other) : b(other.Thing()) {}
|
||||||
|
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass03 : public TestClass02 {
|
||||||
|
public:
|
||||||
|
TestClass03() : c(2) {}
|
||||||
|
TestClass03(const TestClass02& other) : c(other.b) {}
|
||||||
|
TestClass03(const TestClass01& other) : c(other.a) {}
|
||||||
|
TestClass03(const TestClass00& other) : c(other.Thing()) {}
|
||||||
|
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::usertype<TestClass00> s_TestUsertype00(
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>>(),
|
||||||
|
"Thing", &TestClass00::Thing
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass00", s_TestUsertype00);
|
||||||
|
|
||||||
|
sol::usertype<TestClass01> s_TestUsertype01(
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass00>(),
|
||||||
|
"a", &TestClass01::a
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass01", s_TestUsertype01);
|
||||||
|
|
||||||
|
sol::usertype<TestClass02> s_TestUsertype02(
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass01, TestClass00>(),
|
||||||
|
"b", &TestClass02::b
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass02", s_TestUsertype02);
|
||||||
|
|
||||||
|
sol::usertype<TestClass03> s_TestUsertype03(
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
|
||||||
|
"c", &TestClass03::c
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass03", s_TestUsertype03);
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc0 = TestClass00()
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc2 = TestClass02(tc0)
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc1 = TestClass01()
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc3 = TestClass03(tc1)
|
||||||
|
)");
|
||||||
|
|
||||||
|
TestClass00& tc0 = lua["tc0"];
|
||||||
|
TestClass01& tc1 = lua["tc1"];
|
||||||
|
TestClass02& tc2 = lua["tc2"];
|
||||||
|
TestClass03& tc3 = lua["tc3"];
|
||||||
|
REQUIRE(tc1.a == 1);
|
||||||
|
REQUIRE(tc2.a == 1);
|
||||||
|
REQUIRE(tc2.b == 123);
|
||||||
|
REQUIRE(tc3.a == 1);
|
||||||
|
REQUIRE(tc3.b == 2);
|
||||||
|
REQUIRE(tc3.c == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("inheritance/simple-multi-base", "test that multiple bases all work and overloading for constructors works with them") {
|
||||||
|
class TestClass00 {
|
||||||
|
public:
|
||||||
|
int Thing() const { return 123; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass01 : public TestClass00 {
|
||||||
|
public:
|
||||||
|
TestClass01() : a(1) {}
|
||||||
|
TestClass01(const TestClass00& other) : a(other.Thing()) {}
|
||||||
|
|
||||||
|
int a;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass02 : public TestClass01 {
|
||||||
|
public:
|
||||||
|
TestClass02() : b(2) {}
|
||||||
|
TestClass02(const TestClass01& other) : b(other.a) {}
|
||||||
|
TestClass02(const TestClass00& other) : b(other.Thing()) {}
|
||||||
|
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TestClass03 : public TestClass02 {
|
||||||
|
public:
|
||||||
|
TestClass03() : c(2) {}
|
||||||
|
TestClass03(const TestClass02& other) : c(other.b) {}
|
||||||
|
TestClass03(const TestClass01& other) : c(other.a) {}
|
||||||
|
TestClass03(const TestClass00& other) : c(other.Thing()) {}
|
||||||
|
|
||||||
|
int c;
|
||||||
|
};
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::simple_usertype<TestClass00> s_TestUsertype00( lua,
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>>(),
|
||||||
|
"Thing", &TestClass00::Thing
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass00", s_TestUsertype00);
|
||||||
|
|
||||||
|
sol::simple_usertype<TestClass01> s_TestUsertype01( lua,
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass00>(),
|
||||||
|
"a", &TestClass01::a
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass01", s_TestUsertype01);
|
||||||
|
|
||||||
|
sol::simple_usertype<TestClass02> s_TestUsertype02( lua,
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass01, TestClass00>(),
|
||||||
|
"b", &TestClass02::b
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass02", s_TestUsertype02);
|
||||||
|
|
||||||
|
sol::simple_usertype<TestClass03> s_TestUsertype03( lua,
|
||||||
|
sol::call_constructor, sol::constructors<sol::types<>, sol::types<const TestClass02&>, sol::types<const TestClass01&>, sol::types<const TestClass00&>>(),
|
||||||
|
sol::base_classes, sol::bases<TestClass02, TestClass01, TestClass00>(),
|
||||||
|
"c", &TestClass03::c
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.set_usertype("TestClass03", s_TestUsertype03);
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc0 = TestClass00()
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc2 = TestClass02(tc0)
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc1 = TestClass01()
|
||||||
|
)");
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
tc3 = TestClass03(tc1)
|
||||||
|
)");
|
||||||
|
|
||||||
|
TestClass00& tc0 = lua["tc0"];
|
||||||
|
TestClass01& tc1 = lua["tc1"];
|
||||||
|
TestClass02& tc2 = lua["tc2"];
|
||||||
|
TestClass03& tc3 = lua["tc3"];
|
||||||
|
REQUIRE(tc1.a == 1);
|
||||||
|
REQUIRE(tc2.a == 1);
|
||||||
|
REQUIRE(tc2.b == 123);
|
||||||
|
REQUIRE(tc3.a == 1);
|
||||||
|
REQUIRE(tc3.b == 2);
|
||||||
|
REQUIRE(tc3.c == 1);
|
||||||
|
}
|
|
@ -222,21 +222,31 @@ TEST_CASE("usertype/simple-vars", "simple usertype vars can bind various values
|
||||||
lua.new_simple_usertype<test>("test",
|
lua.new_simple_usertype<test>("test",
|
||||||
"straight", sol::var(2),
|
"straight", sol::var(2),
|
||||||
"global", sol::var(muh_variable),
|
"global", sol::var(muh_variable),
|
||||||
"global2", sol::var(through_variable)
|
"global2", sol::var(through_variable),
|
||||||
|
"global3", sol::var(std::ref(through_variable))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
through_variable = 20;
|
||||||
|
|
||||||
lua.script(R"(
|
lua.script(R"(
|
||||||
|
print(test.straight)
|
||||||
s = test.straight
|
s = test.straight
|
||||||
|
print(test.global)
|
||||||
g = test.global
|
g = test.global
|
||||||
|
print(test.global2)
|
||||||
g2 = test.global2
|
g2 = test.global2
|
||||||
|
print(test.global3)
|
||||||
|
g3 = test.global3
|
||||||
)");
|
)");
|
||||||
|
|
||||||
int s = lua["s"];
|
int s = lua["s"];
|
||||||
int g = lua["g"];
|
int g = lua["g"];
|
||||||
int g2 = lua["g2"];
|
int g2 = lua["g2"];
|
||||||
|
int g3 = lua["g3"];
|
||||||
REQUIRE(s == 2);
|
REQUIRE(s == 2);
|
||||||
REQUIRE(g == 10);
|
REQUIRE(g == 10);
|
||||||
REQUIRE(g2 == 25);
|
REQUIRE(g2 == 25);
|
||||||
|
REQUIRE(g3 == 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertypes/simple-variable-control", "test to see if usertypes respond to inheritance and variable controls") {
|
TEST_CASE("usertypes/simple-variable-control", "test to see if usertypes respond to inheritance and variable controls") {
|
||||||
|
@ -377,9 +387,10 @@ TEST_CASE("usertype/simple-runtime-append", "allow extra functions to be appende
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.new_simple_usertype<A>("A");
|
lua.new_simple_usertype<A>("A");
|
||||||
lua.new_simple_usertype<B>("B", sol::base_classes, sol::bases<A>()); // OFFTOP: It crashes here because there's no stuff registered in A usertype( is it an issue? )
|
lua.new_simple_usertype<B>("B", sol::base_classes, sol::bases<A>());
|
||||||
lua.set("b", std::make_unique<B>());
|
lua.set("b", std::make_unique<B>());
|
||||||
lua["A"]["method"] = []() { return 200; };
|
lua["A"]["method"] = []() { return 200; };
|
||||||
|
lua["B"]["method2"] = [](B&) { return 100; };
|
||||||
lua.script("x = b.method()");
|
lua.script("x = b.method()");
|
||||||
lua.script("y = b:method()");
|
lua.script("y = b:method()");
|
||||||
|
|
||||||
|
@ -387,4 +398,11 @@ TEST_CASE("usertype/simple-runtime-append", "allow extra functions to be appende
|
||||||
int y = lua["y"];
|
int y = lua["y"];
|
||||||
REQUIRE(x == 200);
|
REQUIRE(x == 200);
|
||||||
REQUIRE(y == 200);
|
REQUIRE(y == 200);
|
||||||
|
|
||||||
|
lua.script("z = b.method2(b)");
|
||||||
|
lua.script("w = b:method2()");
|
||||||
|
int z = lua["z"];
|
||||||
|
int w = lua["w"];
|
||||||
|
REQUIRE(z == 100);
|
||||||
|
REQUIRE(w == 100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1332,59 +1332,6 @@ print(t.global)
|
||||||
)"));
|
)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/inheritance", "test that metatables are properly inherited") {
|
|
||||||
struct A {
|
|
||||||
int a = 5;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct B {
|
|
||||||
int b() {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct C : B, A {
|
|
||||||
double c = 2.4;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct D : C {
|
|
||||||
bool d() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sol::state lua;
|
|
||||||
lua.new_usertype<A>("A",
|
|
||||||
"a", &A::a
|
|
||||||
);
|
|
||||||
lua.new_usertype<B>("B",
|
|
||||||
"b", &B::b
|
|
||||||
);
|
|
||||||
lua.new_usertype<C>("C",
|
|
||||||
"c", &C::c,
|
|
||||||
sol::base_classes, sol::bases<B, A>()
|
|
||||||
);
|
|
||||||
lua.new_usertype<D>("D",
|
|
||||||
"d", &D::d,
|
|
||||||
sol::base_classes, sol::bases<C, B, A>()
|
|
||||||
);
|
|
||||||
|
|
||||||
lua.script("obj = D.new()");
|
|
||||||
lua.script("d = obj:d()");
|
|
||||||
bool d = lua["d"];
|
|
||||||
lua.script("c = obj.c");
|
|
||||||
double c = lua["c"];
|
|
||||||
lua.script("b = obj:b()");
|
|
||||||
int b = lua["b"];
|
|
||||||
lua.script("a = obj.a");
|
|
||||||
int a = lua["a"];
|
|
||||||
|
|
||||||
REQUIRE(d);
|
|
||||||
REQUIRE(c == 2.4);
|
|
||||||
REQUIRE(b == 10);
|
|
||||||
REQUIRE(a == 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") {
|
TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") {
|
||||||
class Entity {
|
class Entity {
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user