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
|
||||
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
|
||||
sol::load_result script1 = state.load_file("path/to/luascript.lua");
|
||||
sol::load_result script1 = lua.load_file("path/to/luascript.lua");
|
||||
script1(); //execute
|
||||
// load string without execute
|
||||
sol::load_result script2 = state.load("a = 'test'");
|
||||
sol::load_result script2 = lua.load("a = 'test'");
|
||||
script2(); //execute
|
||||
|
||||
sol::load_result script3 = lua.load("return 24");
|
||||
int value2 = script3(); // execute, get return value
|
||||
// value2 == 24
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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
|
||||
-------------------------
|
||||
|
||||
|
|
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();
|
||||
|
||||
inline decltype(auto) base_class_check_key() {
|
||||
static const auto& key = u8"♡o。.(✿ฺ。 ✿ฺ)";
|
||||
static const auto& key = "class_check";
|
||||
return key;
|
||||
}
|
||||
|
||||
inline decltype(auto) base_class_cast_key() {
|
||||
static const auto& key = u8"(◕‿◕✿)";
|
||||
static const auto& key = "class_cast";
|
||||
return key;
|
||||
}
|
||||
|
||||
|
@ -85,11 +85,11 @@ namespace sol {
|
|||
|
||||
template <typename Base, typename... Args>
|
||||
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) {
|
||||
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) {
|
||||
|
|
|
@ -161,18 +161,30 @@ namespace sol {
|
|||
bool mustindex;
|
||||
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>
|
||||
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>
|
||||
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) {
|
||||
callconstructfunc = make_object(L, std::forward<F>(f));
|
||||
callconstructfunc = std::move(o);
|
||||
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>
|
||||
|
@ -182,9 +194,16 @@ namespace sol {
|
|||
|
||||
template <typename N, typename F, meta::enable<is_variable_binding<meta::unqualified_t<F>>> = meta::enabler>
|
||||
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;
|
||||
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>
|
||||
|
@ -194,7 +213,7 @@ namespace sol {
|
|||
callconstructfunc = std::move(o);
|
||||
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>
|
||||
|
@ -204,7 +223,27 @@ namespace sol {
|
|||
callconstructfunc = std::move(o);
|
||||
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>
|
||||
|
@ -224,20 +263,20 @@ namespace sol {
|
|||
newindexbaseclasspropogation = usertype_detail::walk_all_bases<false, Bases...>;
|
||||
}
|
||||
|
||||
private:
|
||||
template<std::size_t... I, typename Tuple>
|
||||
simple_usertype_metatable(usertype_detail::verified_tag, std::index_sequence<I...>, lua_State* L, Tuple&& args)
|
||||
: callconstructfunc(nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(false), secondarymeta(false) {
|
||||
: callconstructfunc(nil),
|
||||
indexfunc(&usertype_detail::indexing_fail<true>), newindexfunc(&usertype_detail::indexing_fail<false>),
|
||||
indexbase(&usertype_detail::simple_core_indexing_call<true>), newindexbase(&usertype_detail::simple_core_indexing_call<false>),
|
||||
indexbaseclasspropogation(usertype_detail::walk_all_bases<true>), newindexbaseclasspropogation(&usertype_detail::walk_all_bases<false>),
|
||||
baseclasscheck(nullptr), baseclasscast(nullptr),
|
||||
mustindex(false), secondarymeta(false) {
|
||||
(void)detail::swallow{ 0,
|
||||
(add(L, detail::forward_get<I * 2>(args), detail::forward_get<I * 2 + 1>(args)),0)...
|
||||
};
|
||||
}
|
||||
|
||||
private:
|
||||
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)...)) {}
|
||||
|
||||
|
|
|
@ -262,16 +262,18 @@ namespace sol {
|
|||
if (lua_getmetatable(L, index) == 0) {
|
||||
return true;
|
||||
}
|
||||
if (stack_detail::check_metatable<U>(L))
|
||||
int metatableindex = lua_gettop(L);
|
||||
if (stack_detail::check_metatable<U>(L, metatableindex))
|
||||
return true;
|
||||
if (stack_detail::check_metatable<U*>(L))
|
||||
if (stack_detail::check_metatable<U*>(L, metatableindex))
|
||||
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;
|
||||
bool success = false;
|
||||
if (detail::has_derived<T>::value) {
|
||||
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) {
|
||||
void* basecastdata = lua_touserdata(L, -1);
|
||||
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace sol {
|
|||
|
||||
template<typename T>
|
||||
class usertype {
|
||||
protected:
|
||||
private:
|
||||
std::unique_ptr<usertype_detail::registrar, detail::deleter> metatableregister;
|
||||
|
||||
template<typename... Args>
|
||||
|
@ -58,6 +58,10 @@ namespace sol {
|
|||
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_detail::registrar* registrar_data() {
|
||||
return metatableregister.get();
|
||||
}
|
||||
|
||||
int push(lua_State* L) {
|
||||
return metatableregister->push_um(L);
|
||||
}
|
||||
|
@ -65,16 +69,17 @@ namespace sol {
|
|||
|
||||
template<typename T>
|
||||
class simple_usertype : public usertype<T> {
|
||||
protected:
|
||||
private:
|
||||
typedef usertype<T> base_t;
|
||||
lua_State* state;
|
||||
|
||||
public:
|
||||
template<typename... Args>
|
||||
simple_usertype(lua_State* L, Args&&... args) : state(L), usertype(simple, L, std::forward<Args>(args)...) {}
|
||||
|
||||
template <typename N, typename F>
|
||||
void add(N&& n, F&& f) {
|
||||
auto meta = (simple_usertype_metatable<T>*) metatableregister.get();
|
||||
simple_usertype(lua_State* L, Args&&... args) : base_t(simple, L, std::forward<Args>(args)...), state(L) {}
|
||||
|
||||
template <typename N, typename F>
|
||||
void set(N&& n, F&& f) {
|
||||
auto meta = static_cast<simple_usertype_metatable<T>*>(base_t::registrar_data());
|
||||
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);
|
||||
string_detail::string_shim accessor = maybeaccessor.value_or(string_detail::string_shim("(unknown)"));
|
||||
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
|
||||
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>
|
||||
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)
|
||||
return;
|
||||
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",
|
||||
"straight", sol::var(2),
|
||||
"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"(
|
||||
print(test.straight)
|
||||
s = test.straight
|
||||
print(test.global)
|
||||
g = test.global
|
||||
print(test.global2)
|
||||
g2 = test.global2
|
||||
print(test.global3)
|
||||
g3 = test.global3
|
||||
)");
|
||||
|
||||
int s = lua["s"];
|
||||
int g = lua["g"];
|
||||
int g2 = lua["g2"];
|
||||
int g3 = lua["g3"];
|
||||
REQUIRE(s == 2);
|
||||
REQUIRE(g == 10);
|
||||
REQUIRE(g2 == 25);
|
||||
REQUIRE(g3 == 20);
|
||||
}
|
||||
|
||||
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;
|
||||
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["A"]["method"] = []() { return 200; };
|
||||
lua["B"]["method2"] = [](B&) { return 100; };
|
||||
lua.script("x = 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"];
|
||||
REQUIRE(x == 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") {
|
||||
class Entity {
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue
Block a user