diff options
Diffstat (limited to 'deps/sol2/examples/source/tutorials')
27 files changed, 1220 insertions, 0 deletions
diff --git a/deps/sol2/examples/source/tutorials/erase_demo.cpp b/deps/sol2/examples/source/tutorials/erase_demo.cpp new file mode 100644 index 0000000..3621a72 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/erase_demo.cpp @@ -0,0 +1,30 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <iostream>
+
+int main() {
+
+ sol::state lua;
+ lua["bark"] = 50;
+ sol::optional<int> x = lua["bark"];
+ // x will have a value
+ if (x) {
+ std::cout << "x has no value, as expected" << std::endl;
+ }
+ else {
+ return -1;
+ }
+
+ lua["bark"] = sol::lua_nil;
+ sol::optional<int> y = lua["bark"];
+ // y will not have a value
+ if (y) {
+ return -1;
+ }
+ else {
+ std::cout << "y has no value, as expected" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/first_snippet.cpp b/deps/sol2/examples/source/tutorials/first_snippet.cpp new file mode 100644 index 0000000..018f9c6 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/first_snippet.cpp @@ -0,0 +1,12 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp> // or #include "sol.hpp", whichever suits your needs
+
+int main(int argc, char* argv[]) {
+
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ lua.script("print('bark bark bark!')");
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/lazy_demo.cpp b/deps/sol2/examples/source/tutorials/lazy_demo.cpp new file mode 100644 index 0000000..b54b705 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/lazy_demo.cpp @@ -0,0 +1,23 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <iostream>
+
+int main() {
+
+ sol::state lua;
+
+ auto barkkey = lua["bark"];
+ if (barkkey.valid()) {
+ // Branch not taken: doesn't exist yet
+ std::cout << "How did you get in here, arf?!" << std::endl;
+ }
+
+ barkkey = 50;
+ if (barkkey.valid()) {
+ // Branch taken: value exists!
+ std::cout << "Bark Bjork Wan Wan Wan" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/object_lifetime.cpp b/deps/sol2/examples/source/tutorials/object_lifetime.cpp new file mode 100644 index 0000000..3ed3f41 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/object_lifetime.cpp @@ -0,0 +1,37 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <string>
+#include <iostream>
+
+int main () {
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ lua.script(R"(
+ obj = "please don't let me die";
+ )");
+
+ sol::object keep_alive = lua["obj"];
+ lua.script(R"(
+ obj = nil;
+ function say(msg)
+ print(msg)
+ end
+ )");
+
+ lua.collect_garbage();
+
+ lua["say"](lua["obj"]);
+ // still accessible here and still alive in Lua
+ // even though the name was cleared
+ std::string message = keep_alive.as<std::string>();
+ std::cout << message << std::endl;
+
+ // Can be pushed back into Lua as an argument
+ // or set to a new name,
+ // whatever you like!
+ lua["say"](keep_alive);
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/open_multiple_libraries.cpp b/deps/sol2/examples/source/tutorials/open_multiple_libraries.cpp new file mode 100644 index 0000000..eab0a2b --- /dev/null +++ b/deps/sol2/examples/source/tutorials/open_multiple_libraries.cpp @@ -0,0 +1,12 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+int main(int argc, char* argv[]) {
+
+ sol::state lua;
+ lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::string, sol::lib::io);
+
+ lua.script("print('bark bark bark!')");
+
+ return 0;
+}
\ No newline at end of file diff --git a/deps/sol2/examples/source/tutorials/pointer_lifetime.cpp b/deps/sol2/examples/source/tutorials/pointer_lifetime.cpp new file mode 100644 index 0000000..84bc536 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/pointer_lifetime.cpp @@ -0,0 +1,75 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+struct my_type {
+ void stuff() {
+ }
+};
+
+int main () {
+
+ sol::state lua;
+
+ /*
+ // AAAHHH BAD
+ // dangling pointer!
+ lua["my_func"] = []() -> my_type* { return new my_type(); };
+
+ // AAAHHH!
+ lua.set("something", new my_type());
+
+ // AAAAAAHHH!!!
+ lua["something_else"] = new my_type();
+ */
+
+ // :ok:
+ lua["my_func0"] = []() -> std::unique_ptr<my_type> { return std::make_unique<my_type>(); };
+
+ // :ok:
+ lua["my_func1"] = []() -> std::shared_ptr<my_type> { return std::make_shared<my_type>(); };
+
+ // :ok:
+ lua["my_func2"] = []() -> my_type { return my_type(); };
+
+ // :ok:
+ lua.set("something", std::unique_ptr<my_type>(new my_type()));
+
+ std::shared_ptr<my_type> my_shared = std::make_shared<my_type>();
+ // :ok:
+ lua.set("something_else", my_shared);
+
+ // :ok:
+ auto my_unique = std::make_unique<my_type>();
+ lua["other_thing"] = std::move(my_unique);
+
+ // :ok:
+ lua["my_func5"] = []() -> my_type* {
+ static my_type mt;
+ return &mt;
+ };
+
+ // THIS IS STILL BAD DON'T DO IT AAAHHH BAD
+ // return a unique_ptr that's empty instead
+ // or be explicit!
+ lua["my_func6"] = []() -> my_type* { return nullptr; };
+
+ // :ok:
+ lua["my_func7"] = []() -> std::nullptr_t { return nullptr; };
+
+ // :ok:
+ lua["my_func8"] = []() -> std::unique_ptr<my_type> {
+ // default-constructs as a nullptr,
+ // gets pushed as nil to Lua
+ return std::unique_ptr<my_type>();
+ // same happens for std::shared_ptr
+ };
+
+ // Acceptable, it will set 'something' to nil
+ // (and delete it on next GC if there's no more references)
+ lua.set("something", nullptr);
+
+ // Also fine
+ lua["something_else"] = nullptr;
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/arguments_to_scripts.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/arguments_to_scripts.cpp new file mode 100644 index 0000000..c96ded4 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/arguments_to_scripts.cpp @@ -0,0 +1,28 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <iostream>
+#include <assert.hpp>
+
+int main(int, char* []) {
+ std::cout << "=== passing arguments to scripts ===" << std::endl;
+
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ const auto& my_script = R"(
+local a,b,c = ...
+print(a,b,c)
+ )";
+
+ sol::load_result fx = lua.load(my_script);
+ if (!fx.valid()) {
+ sol::error err = fx;
+ std::cerr << "failde to load string-based script in the program" << err.what() << std::endl;
+ }
+
+ // prints "your arguments here"
+ fx("your", "arguments", "here");
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_all.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_all.cpp new file mode 100644 index 0000000..822958f --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_all.cpp @@ -0,0 +1,81 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> +#include <iostream> + +void some_function() { + std::cout << "some function!" << std::endl; +} + +void some_other_function() { + std::cout << "some other function!" << std::endl; +} + +struct some_class { + int variable = 30; + + double member_function() { + return 24.5; + } +}; + +int main(int, char*[]) { + std::cout << "=== functions (all) ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // put an instance of "some_class" into lua + // (we'll go into more detail about this later + // just know here that it works and is + // put into lua as a userdata + lua.set("sc", some_class()); + + // binds a plain function + lua["f1"] = some_function; + lua.set_function("f2", &some_other_function); + + // binds just the member function + lua["m1"] = &some_class::member_function; + + // binds the class to the type + lua.set_function("m2", &some_class::member_function, some_class{}); + + // binds just the member variable as a function + lua["v1"] = &some_class::variable; + + // binds class with member variable as function + lua.set_function("v2", &some_class::variable, some_class{}); + + lua.script(R"( + f1() -- some function! + f2() -- some other function! + + -- need class instance if you don't bind it with the function + print(m1(sc)) -- 24.5 + -- does not need class instance: was bound to lua with one + print(m2()) -- 24.5 + + -- need class instance if you + -- don't bind it with the function + print(v1(sc)) -- 30 + -- does not need class instance: + -- it was bound with one + print(v2()) -- 30 + + -- can set, still + -- requires instance + v1(sc, 212) + -- can set, does not need + -- class instance: was bound with one + v2(254) + + print(v1(sc)) -- 212 + print(v2()) -- 254 + )"); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_easy.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_easy.cpp new file mode 100644 index 0000000..748cc8e --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/functions_easy.cpp @@ -0,0 +1,32 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char*[]) { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("function f (a, b, c, d) return 1 end"); + lua.script("function g (a, b) return a + b end"); + + // sol::function is often easier: + // takes a variable number/types of arguments... + sol::function fx = lua["f"]; + // fixed signature std::function<...> + // can be used to tie a sol::function down + std::function<int(int, double, int, std::string)> stdfx = fx; + + int is_one = stdfx(1, 34.5, 3, "bark"); + c_assert(is_one == 1); + int is_also_one = fx(1, "boop", 3, "bark"); + c_assert(is_also_one == 1); + + // call through operator[] + int is_three = lua["g"](1, 2); + c_assert(is_three == 3); + double is_4_8 = lua["g"](2.4, 2.4); + c_assert(is_4_8 == 4.8); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/make_tables.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/make_tables.cpp new file mode 100644 index 0000000..2c8b946 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/make_tables.cpp @@ -0,0 +1,39 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char* []) { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua["abc_sol2"] = lua.create_table_with( + 0, 24 + ); + + sol::table inner_table = lua.create_table_with("bark", 50, + // can reference other existing stuff too + "woof", lua["abc_sol2"] + ); + lua.create_named_table("def_sol2", + "ghi", inner_table + ); + + std::string code = R"( + abc = { [0] = 24 } + def = { + ghi = { + bark = 50, + woof = abc + } + } + )"; + + lua.script(code); + lua.script(R"( + assert(abc_sol2[0] == abc[0]) + assert(def_sol2.ghi.bark == def.ghi.bark) + )"); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_from_lua.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_from_lua.cpp new file mode 100644 index 0000000..2d0d016 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_from_lua.cpp @@ -0,0 +1,23 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char* []) { + sol::state lua; + + lua.script("function f (a, b, c) return a, b, c end"); + + std::tuple<int, int, int> result; + result = lua["f"](100, 200, 300); + // result == { 100, 200, 300 } + int a; + int b; + std::string c; + sol::tie(a, b, c) = lua["f"](100, 200, "bark"); + c_assert(a == 100); + c_assert(b == 200); + c_assert(c == "bark"); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_to_lua.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_to_lua.cpp new file mode 100644 index 0000000..0a0745f --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/multiple_returns_to_lua.cpp @@ -0,0 +1,39 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char* []) { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua["f"] = [](int a, int b, sol::object c) { + // sol::object can be anything here: just pass it through + return std::make_tuple(a, b, c); + }; + + std::tuple<int, int, int> result = lua["f"](100, 200, 300); + const std::tuple<int, int, int> expected(100, 200, 300); + c_assert(result == expected); + + std::tuple<int, int, std::string> result2; + result2 = lua["f"](100, 200, "BARK BARK BARK!"); + const std::tuple<int, int, std::string> expected2(100, 200, "BARK BARK BARK!"); + c_assert(result2 == expected2); + + int a, b; + std::string c; + sol::tie(a, b, c) = lua["f"](100, 200, "bark"); + c_assert(a == 100); + c_assert(b == 200); + c_assert(c == "bark"); + + lua.script(R"( + a, b, c = f(150, 250, "woofbark") + assert(a == 150) + assert(b == 250) + assert(c == "woofbark") + )"); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/namespacing.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/namespacing.cpp new file mode 100644 index 0000000..5a6f553 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/namespacing.cpp @@ -0,0 +1,54 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <iostream> +#include <assert.hpp> + +int main() { + std::cout << "=== namespacing ===" << std::endl; + + struct my_class { + int b = 24; + + int f() const { + return 24; + } + + void g() { + ++b; + } + }; + + sol::state lua; + lua.open_libraries(); + + // "bark" namespacing in Lua + // namespacing is just putting things in a table + // forces creation if it does not exist + auto bark = lua["bark"].get_or_create<sol::table>(); + // equivalent-ish: + //sol::table bark = lua["bark"].force(); // forces table creation + // equivalent, and more flexible: + //sol::table bark = lua["bark"].get_or_create<sol::table>(sol::new_table()); + // equivalent, but less efficient/ugly: + //sol::table bark = lua["bark"] = lua.get_or("bark", lua.create_table()); + bark.new_usertype<my_class>("my_class", + "f", &my_class::f, + "g", &my_class::g); // the usual + + // can add functions, as well (just like the global table) + bark.set_function("print_my_class", [](my_class& self) { std::cout << "my_class { b: " << self.b << " }" << std::endl; }); + + // this works + lua.script("obj = bark.my_class.new()"); + lua.script("obj:g()"); + + // calling this function also works + lua.script("bark.print_my_class(obj)"); + my_class& obj = lua["obj"]; + c_assert(obj.b == 25); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_a_state.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_a_state.cpp new file mode 100644 index 0000000..390d432 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_a_state.cpp @@ -0,0 +1,18 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <iostream> +#include <assert.hpp> + +int main(int, char*[]) { + std::cout << "=== opening a state ===" << std::endl; + + sol::state lua; + // open some common libraries + lua.open_libraries(sol::lib::base, sol::lib::package); + lua.script("print('bark bark bark!')"); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp new file mode 100644 index 0000000..42d74da --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/opening_state_on_raw_lua.cpp @@ -0,0 +1,29 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <iostream> + +int use_sol2(lua_State* L) { + sol::state_view lua(L); + lua.script("print('bark bark bark!')"); + return 0; +} + +int main(int, char*[]) { + std::cout << "=== opening sol::state_view on raw Lua ===" << std::endl; + + lua_State* L = luaL_newstate(); + luaL_openlibs(L); + + lua_pushcclosure(L, &use_sol2, 0); + lua_setglobal(L, "use_sol2"); + + if (luaL_dostring(L, "use_sol2()")) { + lua_error(L); + return -1; + } + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code.cpp new file mode 100644 index 0000000..2ee39cb --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code.cpp @@ -0,0 +1,48 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <fstream> +#include <iostream> +#include <assert.hpp> + +int main(int, char*[]) { + std::cout << "=== running lua code ===" << std::endl; + + { + std::ofstream out("a_lua_script.lua"); + out << "print('hi from a lua script file')"; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // load and execute from string + lua.script("a = 'test'"); + // load and execute from file + lua.script_file("a_lua_script.lua"); + + // run a script, get the result + int value = lua.script("return 54"); + c_assert(value == 54); + + auto bad_code_result = lua.script("123 herp.derp", [](lua_State*, sol::protected_function_result pfr) { + // pfr will contain things that went wrong, for either loading or executing the script + // Can throw your own custom error + // You can also just return it, and let the call-site handle the error if necessary. + return pfr; + }); + // it did not work + c_assert(!bad_code_result.valid()); + + // the default handler panics or throws, depending on your settings + // uncomment for explosions: + //auto bad_code_result_2 = lua.script("bad.code", &sol::script_default_on_error); + + std::cout << std::endl; + + { + std::remove("a_lua_script.lua"); + } + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_low_level.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_low_level.cpp new file mode 100644 index 0000000..350c779 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_low_level.cpp @@ -0,0 +1,49 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <fstream> +#include <iostream> +#include <cstdio> +#include <assert.hpp> + +int main(int, char*[]) { + std::cout << "=== running lua code (low level) ===" << std::endl; + + { + std::ofstream out("a_lua_script.lua"); + out << "print('hi from a lua script file')"; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // load file without execute + sol::load_result script1 = lua.load_file("a_lua_script.lua"); + //execute + script1(); + + // load string without execute + sol::load_result script2 = lua.load("a = 'test'"); + //execute + sol::protected_function_result script2result = script2(); + // optionally, check if it worked + if (script2result.valid()) { + // yay! + } + else { + // aww + } + + sol::load_result script3 = lua.load("return 24"); + // execute, get return value + int value2 = script3(); + c_assert(value2 == 24); + + std::cout << std::endl; + + { + std::remove("a_lua_script.lua"); + } + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_safely.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_safely.cpp new file mode 100644 index 0000000..3248fd2 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/running_lua_code_safely.cpp @@ -0,0 +1,65 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <fstream> +#include <iostream> +#include <assert.hpp> + +int main(int, char*[]) { + std::cout << "=== running lua code (safely) ===" << std::endl; + + { + std::ofstream out("a_lua_script.lua"); + out << "print('hi from a lua script file')"; + } + + sol::state lua; + lua.open_libraries(sol::lib::base); + + // load and execute from string + auto result = lua.safe_script("a = 'test'", sol::script_pass_on_error); + if (!result.valid()) { + sol::error err = result; + std::cerr << "The code has failed to run!\n" << err.what() << "\nPanicking and exiting..." << std::endl; + return 1; + } + + // load and execute from file + auto script_from_file_result = lua.safe_script_file("a_lua_script.lua", sol::script_pass_on_error); + if (!script_from_file_result.valid()) { + sol::error err = script_from_file_result; + std::cerr << "The code from the file has failed to run!\n" << err.what() << "\nPanicking and exiting..." << std::endl; + return 1; + } + + // run a script, get the result + sol::optional<int> maybe_value = lua.safe_script("return 54", sol::script_pass_on_error); + c_assert(maybe_value.has_value()); + c_assert(*maybe_value == 54); + + auto bad_code_result = lua.safe_script("123 herp.derp", sol::script_pass_on_error); + c_assert(!bad_code_result.valid()); + + // you can also specify a handler function, and it'll + // properly work here + auto bad_code_result2 = lua.script("123 herp.derp", [](lua_State*, sol::protected_function_result pfr) { + // pfr will contain things that went wrong, for either loading or executing the script + // Can throw your own custom error + // You can also just return it, and let the call-site handle the error if necessary. + return pfr; + }); + // it did not work + c_assert(!bad_code_result2.valid()); + + // the default handler panics or throws, depending on your settings + // uncomment for explosions: + //auto bad_code_result_2 = lua.script("bad.code", &sol::script_default_on_error); + + std::cout << std::endl; + + { + std::remove("a_lua_script.lua"); + } + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/self_call.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/self_call.cpp new file mode 100644 index 0000000..b839e0b --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/self_call.cpp @@ -0,0 +1,36 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <iostream> + +int main() { + std::cout << "=== self_call ===" << 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; + + return 0; +}
\ No newline at end of file diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables.cpp new file mode 100644 index 0000000..b207ff2 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables.cpp @@ -0,0 +1,83 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char*[]) { + sol::state lua; + lua.open_libraries(sol::lib::base); + + // integer types + lua.set("number", 24); + // floating point numbers + lua["number2"] = 24.5; + // string types + lua["important_string"] = "woof woof"; + // is callable, therefore gets stored as a function that can be called + lua["a_function"] = []() { return 100; }; + // make a table + lua["some_table"] = lua.create_table_with("value", 24); + + + // equivalent to this code + std::string equivalent_code = R"( + t = { + number = 24, + number2 = 24.5, + important_string = "woof woof", + a_function = function () return 100 end, + some_table = { value = 24 } + } + )"; + + // check in Lua + lua.script(equivalent_code); + + lua.script(R"( + assert(t.number == number) + assert(t.number2 == number2) + assert(t.important_string == important_string) + assert(t.a_function() == a_function()) + assert(t.some_table.value == some_table.value) + )"); + + + // implicit conversion + int number = lua["number"]; + c_assert(number == 24); + // explicit get + auto number2 = lua.get<double>("number2"); + c_assert(number2 == 24.5); + // strings too + std::string important_string = lua["important_string"]; + c_assert(important_string == "woof woof"); + // dig into a table + int value = lua["some_table"]["value"]; + c_assert(value == 24); + // get a function + sol::function a_function = lua["a_function"]; + int value_is_100 = a_function(); + // convertible to std::function + std::function<int()> a_std_function = a_function; + int value_is_still_100 = a_std_function(); + c_assert(value_is_100 == 100); + c_assert(value_is_still_100 == 100); + + sol::object number_obj = lua.get<sol::object>("number"); + // sol::type::number + sol::type t1 = number_obj.get_type(); + c_assert(t1 == sol::type::number); + + sol::object function_obj = lua["a_function"]; + // sol::type::function + sol::type t2 = function_obj.get_type(); + c_assert(t2 == sol::type::function); + bool is_it_really = function_obj.is<std::function<int()>>(); + c_assert(is_it_really); + + // will not contain data + sol::optional<int> check_for_me = lua["a_function"]; + c_assert(check_for_me == sol::nullopt); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables_exists.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables_exists.cpp new file mode 100644 index 0000000..3b75166 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/set_and_get_variables_exists.cpp @@ -0,0 +1,20 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char*[]) { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script("exists = 250"); + + int first_try = lua.get_or("exists", 322); + c_assert(first_try == 250); + + lua.set("exists", sol::lua_nil); + int second_try = lua.get_or("exists", 322); + c_assert(second_try == 322); + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/tables_and_nesting.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/tables_and_nesting.cpp new file mode 100644 index 0000000..47b66ff --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/tables_and_nesting.cpp @@ -0,0 +1,46 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> + +int main(int, char*[]) { + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.script(R"( + abc = { [0] = 24 } + def = { + ghi = { + bark = 50, + woof = abc + } + } + )"); + + sol::table abc = lua["abc"]; + sol::table def = lua["def"]; + sol::table ghi = lua["def"]["ghi"]; + + int bark1 = def["ghi"]["bark"]; + int bark2 = lua["def"]["ghi"]["bark"]; + c_assert(bark1 == 50); + c_assert(bark2 == 50); + + int abcval1 = abc[0]; + int abcval2 = ghi["woof"][0]; + c_assert(abcval1 == 24); + c_assert(abcval2 == 24); + + sol::optional<int> will_not_error = lua["abc"]["DOESNOTEXIST"]["ghi"]; + c_assert(will_not_error == sol::nullopt); + + int also_will_not_error = lua["abc"]["def"]["ghi"]["jklm"].get_or(25); + c_assert(also_will_not_error == 25); + + // if you don't go safe, + // will throw (or do at_panic if no exceptions) + //int aaaahhh = lua["boom"]["the_dynamite"]; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata.cpp new file mode 100644 index 0000000..8db4981 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata.cpp @@ -0,0 +1,100 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <assert.hpp> +#include <iostream> + +struct Doge { + int tailwag = 50; + + Doge() { + } + + Doge(int wags) + : tailwag(wags) { + } + + ~Doge() { + std::cout << "Dog at " << this << " is being destroyed..." << std::endl; + } +}; + +int main(int, char* []) { + std::cout << "=== userdata ===" << std::endl; + + sol::state lua; + + Doge dog{ 30 }; + + // fresh one put into Lua + lua["dog"] = Doge{}; + // Copy into lua: destroyed by Lua VM during garbage collection + lua["dog_copy"] = dog; + // OR: move semantics - will call move constructor if present instead + // Again, owned by Lua + lua["dog_move"] = std::move(dog); + lua["dog_unique_ptr"] = std::make_unique<Doge>(25); + lua["dog_shared_ptr"] = std::make_shared<Doge>(31); + + // Identical to above + Doge dog2{ 30 }; + lua.set("dog2", Doge{}); + lua.set("dog2_copy", dog2); + lua.set("dog2_move", std::move(dog2)); + lua.set("dog2_unique_ptr", std::unique_ptr<Doge>(new Doge(25))); + lua.set("dog2_shared_ptr", std::shared_ptr<Doge>(new Doge(31))); + + // Note all of them can be retrieved the same way: + Doge& lua_dog = lua["dog"]; + Doge& lua_dog_copy = lua["dog_copy"]; + Doge& lua_dog_move = lua["dog_move"]; + Doge& lua_dog_unique_ptr = lua["dog_unique_ptr"]; + Doge& lua_dog_shared_ptr = lua["dog_shared_ptr"]; + c_assert(lua_dog.tailwag == 50); + c_assert(lua_dog_copy.tailwag == 30); + c_assert(lua_dog_move.tailwag == 30); + c_assert(lua_dog_unique_ptr.tailwag == 25); + c_assert(lua_dog_shared_ptr.tailwag == 31); + + // lua will treat these types as opaque, and you will be able to pass them around + // to C++ functions and Lua functions alike + + // Use a C++ reference to handle memory directly + // otherwise take by value, without '&' + lua["f"] = [](Doge& dog) { + std::cout << "dog wags its tail " << dog.tailwag << " times!" << std::endl; + }; + + // if you bind a function using a pointer, + // you can handle when `nil` is passed + lua["handling_f"] = [](Doge* dog) { + if (dog == nullptr) { + std::cout << "dog was nil!" << std::endl; + return; + } + std::cout << "dog wags its tail " << dog->tailwag << " times!" << std::endl; + }; + + lua.script(R"( + f(dog) + f(dog_copy) + f(dog_move) + f(dog_unique_ptr) + f(dog_shared_ptr) + + -- C++ arguments that are pointers can handle nil + handling_f(dog) + handling_f(dog_copy) + handling_f(dog_move) + handling_f(dog_unique_ptr) + handling_f(dog_shared_ptr) + handling_f(nil) + + -- never do this + -- f(nil) + )"); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata_memory_reference.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata_memory_reference.cpp new file mode 100644 index 0000000..648cec0 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/userdata_memory_reference.cpp @@ -0,0 +1,65 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <assert.hpp>
+#include <iostream>
+
+struct Doge {
+ int tailwag = 50;
+
+ Doge() {
+ }
+
+ Doge(int wags)
+ : tailwag(wags) {
+ }
+
+ ~Doge() {
+ std::cout << "Dog at " << this << " is being destroyed..." << std::endl;
+ }
+};
+
+int main(int, char* []) {
+ std::cout << "=== userdata memory reference ===" << std::endl;
+
+ sol::state lua;
+ lua.open_libraries(sol::lib::base);
+
+ Doge dog{}; // Kept alive somehow
+
+ // Later...
+ // The following stores a reference, and does not copy/move
+ // lifetime is same as dog in C++
+ // (access after it is destroyed is bad)
+ lua["dog"] = &dog;
+ // Same as above: respects std::reference_wrapper
+ lua["dog"] = std::ref(dog);
+ // These two are identical to above
+ lua.set( "dog", &dog );
+ lua.set( "dog", std::ref( dog ) );
+
+
+ Doge& dog_ref = lua["dog"]; // References Lua memory
+ Doge* dog_pointer = lua["dog"]; // References Lua memory
+ Doge dog_copy = lua["dog"]; // Copies, will not affect lua
+
+ lua.new_usertype<Doge>("Doge",
+ "tailwag", &Doge::tailwag
+ );
+
+ dog_copy.tailwag = 525;
+ // Still 50
+ lua.script("assert(dog.tailwag == 50)");
+
+ dog_ref.tailwag = 100;
+ // Now 100
+ lua.script("assert(dog.tailwag == 100)");
+
+ dog_pointer->tailwag = 345;
+ // Now 345
+ lua.script("assert(dog.tailwag == 345)");
+
+ std::cout << std::endl;
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/quick_n_dirty/usertypes.cpp b/deps/sol2/examples/source/tutorials/quick_n_dirty/usertypes.cpp new file mode 100644 index 0000000..7a820e1 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/quick_n_dirty/usertypes.cpp @@ -0,0 +1,66 @@ +#define SOL_ALL_SAFETIES_ON 1 +#include <sol/sol.hpp> + +#include <iostream> + +struct Doge { + int tailwag = 50; + + Doge() { + } + + Doge(int wags) + : tailwag(wags) { + } + + ~Doge() { + std::cout << "Dog at " << this << " is being destroyed..." << std::endl; + } +}; + +int main(int, char* []) { + std::cout << "=== usertypes ===" << std::endl; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + Doge dog{ 30 }; + + lua["dog"] = Doge{}; + lua["dog_copy"] = dog; + lua["dog_move"] = std::move(dog); + lua["dog_unique_ptr"] = std::make_unique<Doge>(21); + lua["dog_shared_ptr"] = std::make_shared<Doge>(51); + + // now we can access these types in Lua + lua.new_usertype<Doge>( "Doge", + sol::constructors<Doge(), Doge(int)>(), + "tailwag", &Doge::tailwag + ); + lua.script(R"( + function f (dog) + if dog == nil then + print('dog was nil!') + return + end + print('dog wags its tail ' .. dog.tailwag .. ' times!') + end + )"); + + lua.script(R"( + dog_lua = Doge.new() + + f(dog_lua) + f(dog) + f(dog_copy) + f(dog_move) + f(dog) + f(dog_unique_ptr) + f(dog_shared_ptr) + f(nil) + )"); + + std::cout << std::endl; + + return 0; +} diff --git a/deps/sol2/examples/source/tutorials/variables_demo.cpp b/deps/sol2/examples/source/tutorials/variables_demo.cpp new file mode 100644 index 0000000..d5228d1 --- /dev/null +++ b/deps/sol2/examples/source/tutorials/variables_demo.cpp @@ -0,0 +1,71 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <tuple>
+#include <assert.hpp>
+#include <utility> // for std::pair
+
+int main() {
+
+ sol::state lua;
+ /*
+ lua.script_file("variables.lua");
+ */
+ lua.script(R"(
+config = {
+ fullscreen = false,
+ resolution = { x = 1024, y = 768 }
+}
+ )");
+ // the type "sol::state" behaves
+ // exactly like a table!
+ bool isfullscreen = lua["config"]["fullscreen"]; // can get nested variables
+ sol::table config = lua["config"];
+ c_assert(!isfullscreen);
+
+ // can also get it using the "get" member function
+ // auto replaces the unqualified type name
+ auto resolution = config.get<sol::table>("resolution");
+
+ // table and state can have multiple things pulled out of it too
+ std::tuple<int, int> xyresolutiontuple = resolution.get<int, int>("x", "y");
+ c_assert(std::get<0>(xyresolutiontuple) == 1024);
+ c_assert(std::get<1>(xyresolutiontuple) == 768);
+
+ // test variable
+ auto bark = lua["config"]["bark"];
+ if (bark.valid()) {
+ // branch not taken: config and/or bark are not variables
+ }
+ else {
+ // Branch taken: config and bark are existing variables
+ }
+
+ // can also use optional
+ sol::optional<int> not_an_integer = lua["config"]["fullscreen"];
+ if (not_an_integer) {
+ // Branch not taken: value is not an integer
+ }
+
+ sol::optional<bool> is_a_boolean = lua["config"]["fullscreen"];
+ if (is_a_boolean) {
+ // Branch taken: the value is a boolean
+ }
+
+ sol::optional<double> does_not_exist = lua["not_a_variable"];
+ if (does_not_exist) {
+ // Branch not taken: that variable is not present
+ }
+
+ // this will result in a value of '24'
+ // (it tries to get a number, and fullscreen is
+ // not a number
+ int is_defaulted = lua["config"]["fullscreen"].get_or(24);
+ c_assert(is_defaulted == 24);
+
+ // This will result in the value of the config, which is 'false'
+ bool is_not_defaulted = lua["config"]["fullscreen"];
+ c_assert(!is_not_defaulted);
+
+ return 0;
+}
diff --git a/deps/sol2/examples/source/tutorials/write_variables_demo.cpp b/deps/sol2/examples/source/tutorials/write_variables_demo.cpp new file mode 100644 index 0000000..22d195a --- /dev/null +++ b/deps/sol2/examples/source/tutorials/write_variables_demo.cpp @@ -0,0 +1,39 @@ +#define SOL_ALL_SAFETIES_ON 1
+#include <sol/sol.hpp>
+
+#include <iostream>
+
+int main() {
+
+ sol::state lua;
+
+ // open those basic lua libraries
+ // again, for print() and other basic utilities
+ lua.open_libraries(sol::lib::base);
+
+ // value in the global table
+ lua["bark"] = 50;
+
+ // a table being created in the global table
+ lua["some_table"] = lua.create_table_with(
+ "key0", 24,
+ "key1", 25,
+ lua["bark"], "the key is 50 and this string is its value!");
+
+ // Run a plain ol' string of lua code
+ // Note you can interact with things set through sol in C++ with lua!
+ // Using a "Raw String Literal" to have multi-line goodness:
+ // http://en.cppreference.com/w/cpp/language/string_literal
+ lua.script(R"(
+
+ print(some_table[50])
+ print(some_table["key0"])
+ print(some_table["key1"])
+
+ -- a lua comment: access a global in a lua script with the _G table
+ print(_G["bark"])
+
+ )");
+
+ return 0;
+}
|