Add dependencies locally

This commit is contained in:
Ahrimdon
2024-03-07 03:33:59 -05:00
parent 7efc76aca0
commit 382a3e7433
9212 changed files with 3060871 additions and 17 deletions

View File

@ -0,0 +1,32 @@
#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;
}

View File

@ -0,0 +1,15 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp> // or #include "sol.hpp", whichever suits your needs
int main(int argc, char* argv[]) {
// silence unused warnings
(void)argc;
(void)argv;
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.script("print('bark bark bark!')");
return 0;
}

View File

@ -0,0 +1,24 @@
#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;
}

View File

@ -0,0 +1,22 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
int main() {
sol::state lua;
lua.script("function f (a, b, c) return a, b, c end");
std::tuple<int, int, int> result;
result = lua["f"](1, 2, 3);
SOL_ASSERT(result == std::make_tuple(1, 2, 3));
int a, b;
std::string c;
// NOTE: sol::tie, NOT std::tie
// (ESS OH ELL prefix, not ESS TEE DEE prefix)
sol::tie(a, b, c) = lua["f"](1, 2, "bark");
SOL_ASSERT(a == 1);
SOL_ASSERT(b == 2);
SOL_ASSERT(c == "bark");
return 0;
}

View File

@ -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;
}

View File

@ -0,0 +1,17 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
int main(int argc, char* argv[]) {
// silence unused warnings
(void)argc;
(void)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;
}

View File

@ -0,0 +1,82 @@
#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;
}

View File

@ -0,0 +1,30 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>
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 << "failed to load string-based script into "
"the program"
<< err.what() << std::endl;
}
// prints "your arguments here"
fx("your", "arguments", "here");
return 0;
}

View File

@ -0,0 +1,82 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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;
}

View File

@ -0,0 +1,32 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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");
SOL_ASSERT(is_one == 1);
int is_also_one = fx(1, "boop", 3, "bark");
SOL_ASSERT(is_also_one == 1);
// call through operator[]
int is_three = lua["g"](1, 2);
SOL_ASSERT(is_three == 3);
double is_4_8 = lua["g"](2.4, 2.4);
SOL_ASSERT(is_4_8 == 4.8);
return 0;
}

View File

@ -0,0 +1,35 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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;
}

View File

@ -0,0 +1,22 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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");
SOL_ASSERT(a == 100);
SOL_ASSERT(b == 200);
SOL_ASSERT(c == "bark");
return 0;
}

View File

@ -0,0 +1,40 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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);
SOL_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!");
SOL_ASSERT(result2 == expected2);
int a, b;
std::string c;
sol::tie(a, b, c) = lua["f"](100, 200, "bark");
SOL_ASSERT(a == 100);
SOL_ASSERT(b == 200);
SOL_ASSERT(c == "bark");
lua.script(R"(
a, b, c = f(150, 250, "woofbark")
assert(a == 150)
assert(b == 250)
assert(c == "woofbark")
)");
return 0;
}

View File

@ -0,0 +1,59 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>
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"];
SOL_ASSERT(obj.b == 25);
std::cout << std::endl;
return 0;
}

View File

@ -0,0 +1,17 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <iostream>
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;
}

View File

@ -0,0 +1,30 @@
#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;
}

View File

@ -0,0 +1,48 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <fstream>
#include <iostream>
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");
SOL_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
SOL_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;
}

View File

@ -0,0 +1,48 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <fstream>
#include <iostream>
#include <cstdio>
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();
SOL_ASSERT(value2 == 24);
std::cout << std::endl;
{ std::remove("a_lua_script.lua"); }
return 0;
}

View File

@ -0,0 +1,75 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <fstream>
#include <iostream>
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);
SOL_ASSERT(maybe_value.has_value());
SOL_ASSERT(*maybe_value == 54);
auto bad_code_result = lua.safe_script(
"123 herp.derp", sol::script_pass_on_error);
SOL_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
SOL_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;
}

View File

@ -0,0 +1,37 @@
#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;
}

View File

@ -0,0 +1,83 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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"];
SOL_ASSERT(number == 24);
// explicit get
auto number2 = lua.get<double>("number2");
SOL_ASSERT(number2 == 24.5);
// strings too
std::string important_string = lua["important_string"];
SOL_ASSERT(important_string == "woof woof");
// dig into a table
int value = lua["some_table"]["value"];
SOL_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();
SOL_ASSERT(value_is_100 == 100);
SOL_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();
SOL_ASSERT(t1 == sol::type::number);
sol::object function_obj = lua["a_function"];
// sol::type::function
sol::type t2 = function_obj.get_type();
SOL_ASSERT(t2 == sol::type::function);
bool is_it_really = function_obj.is<std::function<int()>>();
SOL_ASSERT(is_it_really);
// will not contain data
sol::optional<int> check_for_me = lua["a_function"];
SOL_ASSERT(check_for_me == sol::nullopt);
return 0;
}

View File

@ -0,0 +1,19 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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);
SOL_ASSERT(first_try == 250);
lua.set("exists", sol::lua_nil);
int second_try = lua.get_or("exists", 322);
SOL_ASSERT(second_try == 322);
return 0;
}

View File

@ -0,0 +1,47 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.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"];
SOL_ASSERT(bark1 == 50);
SOL_ASSERT(bark2 == 50);
int abcval1 = abc[0];
int abcval2 = ghi["woof"][0];
SOL_ASSERT(abcval1 == 24);
SOL_ASSERT(abcval2 == 24);
sol::optional<int> will_not_error
= lua["abc"]["DOESNOTEXIST"]["ghi"];
SOL_ASSERT(will_not_error == sol::nullopt);
int also_will_not_error
= lua["abc"]["def"]["ghi"]["jklm"].get_or(25);
SOL_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;
}

View File

@ -0,0 +1,105 @@
#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 << "=== 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"];
SOL_ASSERT(lua_dog.tailwag == 50);
SOL_ASSERT(lua_dog_copy.tailwag == 30);
SOL_ASSERT(lua_dog_move.tailwag == 30);
SOL_ASSERT(lua_dog_unique_ptr.tailwag == 25);
SOL_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;
}

View File

@ -0,0 +1,63 @@
#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 << "=== 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;
}

View File

@ -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;
}

View File

@ -0,0 +1,29 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
int main() {
sol::state lua;
lua.script(R"(
function f (a)
return a + 5
end
)");
// Get and immediately call
int x = lua["f"](30);
SOL_ASSERT(x == 35);
// Store it into a variable first, then call
sol::unsafe_function f = lua["f"];
int y = f(20);
SOL_ASSERT(y == 25);
// Store it into a variable first, then call
sol::protected_function safe_f = lua["f"];
int z = safe_f(45);
SOL_ASSERT(z == 50);
return 0;
}

View File

@ -0,0 +1,79 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <tuple>
#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"];
SOL_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");
SOL_ASSERT(std::get<0>(xyresolutiontuple) == 1024);
SOL_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);
SOL_ASSERT(is_defaulted == 24);
// This will result in the value of the config, which is
// 'false'
bool is_not_defaulted = lua["config"]["fullscreen"];
SOL_ASSERT(!is_not_defaulted);
return 0;
}

View File

@ -0,0 +1,42 @@
#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;
}

View File

@ -0,0 +1,28 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
std::string my_function(int D_count, std::string original) {
// Create a string with the letter 'D' "D_count" times,
// append it to 'original'
return original + std::string(D_count, 'D');
}
int main() {
sol::state lua;
lua["my_func"] = my_function; // way 1
lua.set("my_func", my_function); // way 2
lua.set_function("my_func", my_function); // way 3
// This function is now accessible as 'my_func' in
// lua scripts / code run on this state:
lua.script("some_str = my_func(1, 'Da')");
// Read out the global variable we stored in 'some_str' in
// the quick lua code we just executed
std::string some_str = lua["some_str"];
SOL_ASSERT(some_str == "DaD");
return 0;
}

View File

@ -0,0 +1,52 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
struct my_class {
int a = 0;
my_class(int x) : a(x) {
}
int func() {
++a; // increment a by 1
return a;
}
};
int main() {
sol::state lua;
lua.open_libraries(sol::lib::base);
// Here, we are binding the member function and a class
// instance: it will call the function on the given class
// instance
lua.set_function(
"my_class_func", &my_class::func, my_class(0));
// We do not pass a class instance here:
// the function will need you to pass an instance of
// "my_class" to it in lua to work, as shown below
lua.set_function("my_class_func_2", &my_class::func);
// With a pre-bound instance:
lua.script(R"(
first_value = my_class_func()
second_value = my_class_func()
assert(first_value == 1)
assert(second_value == 2)
)");
// With no bound instance:
lua.set("obj", my_class(24));
// Calls "func" on the class instance
// referenced by "obj" in Lua
lua.script(R"(
third_value = my_class_func_2(obj)
fourth_value = my_class_func_2(obj)
assert(third_value == 25)
assert(fourth_value == 26)
)");
return 0;
}

View File

@ -0,0 +1,29 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
template <typename A, typename B>
auto my_add(A a, B b) {
return a + b;
}
int main() {
sol::state lua;
auto int_function_pointer = &my_add<int, int>;
auto string_function_pointer
= &my_add<std::string, std::string>;
// adds 2 integers, or "adds" (concatenates) two strings
lua["my_combine"] = sol::overload(
int_function_pointer, string_function_pointer);
lua.script("my_num = my_combine(1, 2)");
lua.script(
"my_str = my_combine('bark bark', ' woof woof')");
int my_num = lua["my_num"];
std::string my_str = lua["my_str"];
SOL_ASSERT(my_num == 3);
SOL_ASSERT(my_str == "bark bark woof woof");
return 0;
}

View File

@ -0,0 +1,33 @@
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
template <typename A, typename B>
auto my_add(A a, B b) {
return a + b;
}
int main() {
sol::state lua;
// adds 2 integers
auto int_function_pointer = &my_add<int, int>;
lua["my_int_add"] = int_function_pointer;
// concatenates 2 strings
auto string_function_pointer
= &my_add<std::string, std::string>;
lua["my_string_combine"] = string_function_pointer;
lua.script("my_num = my_int_add(1, 2)");
int my_num = lua["my_num"];
SOL_ASSERT(my_num == 3);
lua.script(
"my_str = my_string_combine('bark bark', ' woof "
"woof')");
std::string my_str = lua["my_str"];
SOL_ASSERT(my_str == "bark bark woof woof");
return 0;
}