mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
update examples, support inherited usertype metatables, and beef up wording and fix other crap in docs
Addresses #157 temporarily
This commit is contained in:
parent
4aea285769
commit
5460f7e626
38
bootstrap.py
38
bootstrap.py
|
@ -132,6 +132,24 @@ if 'win32' in sys.platform:
|
||||||
else:
|
else:
|
||||||
tests = os.path.join(builddir, 'tests')
|
tests = os.path.join(builddir, 'tests')
|
||||||
|
|
||||||
|
tests_inputs = []
|
||||||
|
tests_object_files = []
|
||||||
|
for f in glob.glob('test*.cpp'):
|
||||||
|
obj = object_file(f)
|
||||||
|
tests_inputs.append(f)
|
||||||
|
tests_object_files.append(obj)
|
||||||
|
|
||||||
|
examples = []
|
||||||
|
examples_input = []
|
||||||
|
for f in glob.glob('examples/*.cpp'):
|
||||||
|
if 'win32' in sys.platform:
|
||||||
|
example = os.path.join(builddir, replace_extension(f, '.exe'))
|
||||||
|
else:
|
||||||
|
example = os.path.join(builddir, replace_extension(f, ''))
|
||||||
|
examples_input.append(f)
|
||||||
|
examples.append(example)
|
||||||
|
|
||||||
|
|
||||||
# ninja file
|
# ninja file
|
||||||
ninja = ninja_syntax.Writer(open('build.ninja', 'w'))
|
ninja = ninja_syntax.Writer(open('build.ninja', 'w'))
|
||||||
|
|
||||||
|
@ -149,7 +167,8 @@ ninja.rule('compile', command = '$cxx -MMD -MF $out.d -c $cxxflags -Werror $in -
|
||||||
deps = 'gcc', depfile = '$out.d',
|
deps = 'gcc', depfile = '$out.d',
|
||||||
description = 'Compiling $in to $out')
|
description = 'Compiling $in to $out')
|
||||||
ninja.rule('link', command = '$cxx $cxxflags $in -o $out $ldflags', description = 'Creating $out')
|
ninja.rule('link', command = '$cxx $cxxflags $in -o $out $ldflags', description = 'Creating $out')
|
||||||
ninja.rule('runner', command = tests)
|
ninja.rule('tests_runner', command = tests)
|
||||||
|
ninja.rule('examples_runner', command = 'cmd /c ' + (' && '.join(examples)) if 'win32' in sys.platform else ' && '.join(examples) )
|
||||||
ninja.rule('example', command = '$cxx $cxxflags $in -o $out $ldflags')
|
ninja.rule('example', command = '$cxx $cxxflags $in -o $out $ldflags')
|
||||||
ninja.rule('installer', command = copy_command)
|
ninja.rule('installer', command = copy_command)
|
||||||
ninja.rule('uninstaller', command = remove_command)
|
ninja.rule('uninstaller', command = remove_command)
|
||||||
|
@ -158,22 +177,17 @@ ninja.newline()
|
||||||
# builds
|
# builds
|
||||||
ninja.build('build.ninja', 'bootstrap', implicit = sys.argv[0])
|
ninja.build('build.ninja', 'bootstrap', implicit = sys.argv[0])
|
||||||
|
|
||||||
tests_object_files = []
|
for obj, f in zip(tests_object_files, tests_inputs):
|
||||||
for f in glob.glob('test*.cpp'):
|
|
||||||
obj = object_file(f)
|
|
||||||
tests_object_files.append(obj)
|
|
||||||
ninja.build(obj, 'compile', inputs = f)
|
ninja.build(obj, 'compile', inputs = f)
|
||||||
|
|
||||||
examples = []
|
for example, f in zip(examples, examples_input):
|
||||||
for f in glob.glob('examples/*.cpp'):
|
|
||||||
example = os.path.join(builddir, replace_extension(f, ''))
|
|
||||||
examples.append(example)
|
|
||||||
ninja.build(example, 'example', inputs = f)
|
ninja.build(example, 'example', inputs = f)
|
||||||
|
|
||||||
ninja.build(tests, 'link', inputs = tests_object_files)
|
ninja.build(tests, 'link', inputs = tests_object_files)
|
||||||
ninja.build('tests', 'phony', inputs = tests)
|
ninja.build('tests', 'phony', inputs = tests)
|
||||||
|
ninja.build('examples', 'phony', inputs = examples)
|
||||||
ninja.build('install', 'installer', inputs = args.install_dir)
|
ninja.build('install', 'installer', inputs = args.install_dir)
|
||||||
ninja.build('uninstall', 'uninstaller')
|
ninja.build('uninstall', 'uninstaller')
|
||||||
ninja.build('examples', 'phony', inputs = examples)
|
ninja.build('run', 'tests_runner', implicit = 'tests')
|
||||||
ninja.build('run', 'runner', implicit = 'tests')
|
ninja.build('run_examples', 'examples_runner', implicit = 'examples')
|
||||||
ninja.default('run')
|
ninja.default('run run_examples')
|
||||||
|
|
|
@ -7,6 +7,8 @@ The sole purpose of this tagging type is to work with :doc:`usertypes<usertype>`
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
struct test {
|
struct test {
|
||||||
static int muh_variable;
|
static int muh_variable;
|
||||||
};
|
};
|
||||||
|
@ -19,10 +21,10 @@ The sole purpose of this tagging type is to work with :doc:`usertypes<usertype>`
|
||||||
lua.new_usertype<test>("test",
|
lua.new_usertype<test>("test",
|
||||||
"direct", sol::var(2),
|
"direct", sol::var(2),
|
||||||
"global", sol::var(test::muh_variable),
|
"global", sol::var(test::muh_variable),
|
||||||
"ref_global", sol::var(std::ref(test::muh_variable)),
|
"ref_global", sol::var(std::ref(test::muh_variable))
|
||||||
);
|
);
|
||||||
|
|
||||||
int direct_value = lua["test"]["straight"];
|
int direct_value = lua["test"]["direct"];
|
||||||
// direct_value == 2
|
// direct_value == 2
|
||||||
|
|
||||||
int global = lua["test"]["global"];
|
int global = lua["test"]["global"];
|
||||||
|
|
|
@ -8,13 +8,17 @@ transparent argument to deal with multiple parameters to a function
|
||||||
|
|
||||||
struct variadic_args;
|
struct variadic_args;
|
||||||
|
|
||||||
This class is meant to represent every single argument at its current index and beyond in a function list. It does not increment the argument count and is thus transparent. You can place it anyway in the argument list, and it will represent all of the objects in a function call that come after it, whether they are listed explicitly or not.
|
This class is meant to represent every single argument at its current index and beyond in a function list. It does not increment the argument count and is thus transparent. You can place it anywhere in the argument list, and it will represent all of the objects in a function call that come after it, whether they are listed explicitly or not.
|
||||||
|
|
||||||
``variadic_args`` also has ``begin()`` and ``end()`` functions that return (almost) random-acess iterators. These return a proxy type that can be implicitly converted, much like the :doc:`table proxy type<proxy>`.
|
``variadic_args`` also has ``begin()`` and ``end()`` functions that return (almost) random-acess iterators. These return a proxy type that can be implicitly converted, much like the :doc:`table proxy type<proxy>`.
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
int main () {
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
// Function requires 2 arguments
|
// Function requires 2 arguments
|
||||||
|
@ -22,7 +26,7 @@ This class is meant to represent every single argument at its current index and
|
||||||
// va will include everything after "a" argument,
|
// va will include everything after "a" argument,
|
||||||
// which means "b" will be part of the varaidic_args list too
|
// which means "b" will be part of the varaidic_args list too
|
||||||
// at position 0
|
// at position 0
|
||||||
lua.set_function("v", [](sol::this_state, int a, sol::variadic_args va, int b) {
|
lua.set_function("v", [](int a, sol::variadic_args va, int b) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
for (auto v : va) {
|
for (auto v : va) {
|
||||||
int value = v; // get argument out (implicit conversion)
|
int value = v; // get argument out (implicit conversion)
|
||||||
|
@ -42,3 +46,4 @@ This class is meant to represent every single argument at its current index and
|
||||||
lua.script("print(x)"); // 50
|
lua.script("print(x)"); // 50
|
||||||
lua.script("print(x2)"); // 600
|
lua.script("print(x2)"); // 600
|
||||||
lua.script("print(x3)"); // 21
|
lua.script("print(x3)"); // 21
|
||||||
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ This is the base formula that you can follow to extend to your own classes. Usin
|
||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
#include <two_things.hpp>
|
#include <two_things.hpp>
|
||||||
|
|
||||||
int main (int argc, char* argv[]) {
|
int main () {
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ Take this ``player`` struct in C++ in a header file:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_hp(int value) {
|
void set_hp(int value) {
|
||||||
hp = value;
|
hp = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ Take this ``player`` struct in C++ in a header file:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int hp;
|
int hp;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
It's a fairly minimal class, but we don't want to have to rewrite this with metatables in Lua. We want this to be part of Lua easily. The following is the Lua code that we'd like to have work properly:
|
It's a fairly minimal class, but we don't want to have to rewrite this with metatables in Lua. We want this to be part of Lua easily. The following is the Lua code that we'd like to have work properly:
|
||||||
|
@ -92,6 +92,9 @@ To do this, you bind things using the ``new_usertype`` and ``set_usertype`` meth
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
:caption: player_script.cpp
|
:caption: player_script.cpp
|
||||||
|
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
int main () {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
// note that you can set a
|
// note that you can set a
|
||||||
|
@ -123,6 +126,7 @@ To do this, you bind things using the ``new_usertype`` and ``set_usertype`` meth
|
||||||
);
|
);
|
||||||
|
|
||||||
lua.script_file("player_script.lua");
|
lua.script_file("player_script.lua");
|
||||||
|
}
|
||||||
|
|
||||||
That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. You can even bind global variables (even by reference with ``std::ref``) with ``sol::var``. There's a lot to try out!
|
That script should run fine now, and you can observe and play around with the values. Even more stuff :doc:`you can do<../api/usertype>` is described elsewhere, like initializer functions (private constructors / destructors support), "static" functions callable with ``name.my_function( ... )``, and overloaded member functions. You can even bind global variables (even by reference with ``std::ref``) with ``sol::var``. There's a lot to try out!
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,7 @@ You can get anything that's a callable in Lua, including C++ functions you bind
|
||||||
function f (a)
|
function f (a)
|
||||||
if a < 0 then
|
if a < 0 then
|
||||||
error("negative number detected")
|
error("negative number detected")
|
||||||
|
end
|
||||||
return a + 5
|
return a + 5
|
||||||
end
|
end
|
||||||
)");
|
)");
|
||||||
|
@ -224,7 +225,7 @@ You can get anything that's a callable in Lua, including C++ functions you bind
|
||||||
sol::protected_function_result result = f(-500);
|
sol::protected_function_result result = f(-500);
|
||||||
if (result.valid()) {
|
if (result.valid()) {
|
||||||
// Call succeeded
|
// Call succeeded
|
||||||
int x = r1esult;
|
int x = result;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Call failed
|
// Call failed
|
||||||
|
@ -269,6 +270,7 @@ You can also return mutiple items yourself from a C++-bound function. Here, we'r
|
||||||
:caption: Multiple returns into Lua
|
:caption: Multiple returns into Lua
|
||||||
:name: multi-return-cxx-functions
|
:name: multi-return-cxx-functions
|
||||||
|
|
||||||
|
int main () {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
lua["f"] = [](int a, int b, sol::object c) {
|
lua["f"] = [](int a, int b, sol::object c) {
|
||||||
|
@ -289,6 +291,7 @@ You can also return mutiple items yourself from a C++-bound function. Here, we'r
|
||||||
// a == 1
|
// a == 1
|
||||||
// b == 2
|
// b == 2
|
||||||
// c == "meow"
|
// c == "meow"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Note here that we use :doc:`sol::object<../api/object>` to transport through "any value" that can come from Lua. You can also use ``sol::make_object`` to create an object from some value, so that it can be returned into Lua as well.
|
Note here that we use :doc:`sol::object<../api/object>` to transport through "any value" that can come from Lua. You can also use ``sol::make_object`` to create an object from some value, so that it can be returned into Lua as well.
|
||||||
|
@ -307,7 +310,7 @@ It can be used like so, inconjunction with ``sol::this_state``:
|
||||||
:name: object-return-cxx-functions
|
:name: object-return-cxx-functions
|
||||||
|
|
||||||
sol::object fancy_func (sol::object a, sol::object b, sol::this_state s) {
|
sol::object fancy_func (sol::object a, sol::object b, sol::this_state s) {
|
||||||
sol::state_view lua = s;
|
sol::state_view lua(s);
|
||||||
if (a.is<int>() && b.is<int>()) {
|
if (a.is<int>() && b.is<int>()) {
|
||||||
return sol::make_object(lua, a.as<int>() + b.as<int>());
|
return sol::make_object(lua, a.as<int>() + b.as<int>());
|
||||||
}
|
}
|
||||||
|
@ -318,6 +321,7 @@ It can be used like so, inconjunction with ``sol::this_state``:
|
||||||
return sol::make_object(lua, sol::nil);
|
return sol::make_object(lua, sol::nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main () {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
lua["f"] = fancy_func;
|
lua["f"] = fancy_func;
|
||||||
|
@ -331,6 +335,7 @@ It can be used like so, inconjunction with ``sol::this_state``:
|
||||||
lua.script("result3 = f(true, 5.5)");
|
lua.script("result3 = f(true, 5.5)");
|
||||||
double result3 = lua["result3"];
|
double result3 = lua["result3"];
|
||||||
// result3 == 16.5
|
// result3 == 16.5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua<cxx-in-lua>`!
|
This covers almost everything you need to know about Functions and how they interact with Sol. For some advanced tricks and neat things, check out :doc:`sol::this_state<../api/this_state>` and :doc:`sol::variadic_args<../api/variadic_args>`. The next stop in this tutorial is about :doc:`C++ types (usertypes) in Lua<cxx-in-lua>`!
|
41
examples/any_return.cpp
Normal file
41
examples/any_return.cpp
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Uses some of the fancier bits of sol2, including the "transparent argument",
|
||||||
|
// sol::this_state, which gets the current state and does not increment
|
||||||
|
// function arguments
|
||||||
|
sol::object fancy_func(sol::object a, sol::object b, sol::this_state s) {
|
||||||
|
sol::state_view lua(s);
|
||||||
|
if (a.is<int>() && b.is<int>()) {
|
||||||
|
return sol::make_object(lua, a.as<int>() + b.as<int>());
|
||||||
|
}
|
||||||
|
else if (a.is<bool>()) {
|
||||||
|
bool do_triple = a.as<bool>();
|
||||||
|
return sol::make_object(lua, b.as<double>() * (do_triple ? 3 : 1));
|
||||||
|
}
|
||||||
|
return sol::make_object(lua, sol::nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua["f"] = fancy_func;
|
||||||
|
|
||||||
|
int result = lua["f"](1, 2);
|
||||||
|
// result == 3
|
||||||
|
double result2 = lua["f"](false, 2.5);
|
||||||
|
// result2 == 2.5
|
||||||
|
|
||||||
|
// call in Lua, get result
|
||||||
|
// notice we only need 2 arguments here, not 3 (sol::this_state is transparent)
|
||||||
|
lua.script("result3 = f(true, 5.5)");
|
||||||
|
double result3 = lua["result3"];
|
||||||
|
// result3 == 16.5
|
||||||
|
|
||||||
|
std::cout << "=== any_return example ===" << std::endl;
|
||||||
|
std::cout << "result : " << result << std::endl;
|
||||||
|
std::cout << "result2: " << result2 << std::endl;
|
||||||
|
std::cout << "result3: " << result3 << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
|
@ -1,5 +1,7 @@
|
||||||
#include <sol.hpp>
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// create an empty lua state
|
// create an empty lua state
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
@ -10,5 +12,8 @@ int main() {
|
||||||
lua.open_libraries(sol::lib::base);
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
// call lua code directly
|
// call lua code directly
|
||||||
|
std::cout << "=== basic example ===" << std::endl;
|
||||||
lua.script("print('hello world')");
|
lua.script("print('hello world')");
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
|
@ -19,9 +19,17 @@ struct config {
|
||||||
int main() {
|
int main() {
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
config screen;
|
config screen;
|
||||||
lua.script_file("config.lua");
|
// To use the file, uncomment here and make sure it is in local dir
|
||||||
|
//lua.script_file("config.lua");
|
||||||
|
lua.script(R"(
|
||||||
|
name = "Asus"
|
||||||
|
width = 1920
|
||||||
|
height = 1080
|
||||||
|
)");
|
||||||
screen.name = lua.get<std::string>("name");
|
screen.name = lua.get<std::string>("name");
|
||||||
screen.width = lua.get<int>("width");
|
screen.width = lua.get<int>("width");
|
||||||
screen.height = lua.get<int>("height");
|
screen.height = lua.get<int>("height");
|
||||||
|
std::cout << "=== config example ===" << std::endl;
|
||||||
screen.print();
|
screen.print();
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
80
examples/customization.cpp
Normal file
80
examples/customization.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
struct two_things {
|
||||||
|
int a;
|
||||||
|
bool b;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sol {
|
||||||
|
|
||||||
|
// First, the expected size
|
||||||
|
// Specialization of a struct
|
||||||
|
template <>
|
||||||
|
struct lua_size<two_things> : std::integral_constant<int, 2> {};
|
||||||
|
|
||||||
|
// Now, specialize various stack structures
|
||||||
|
namespace stack {
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct checker<two_things> {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
|
||||||
|
// Check first and second second index for being the proper types
|
||||||
|
bool success = stack::check<int>(L, index, handler)
|
||||||
|
&& stack::check<bool>(L, index + 1, handler);
|
||||||
|
tracking.use(2);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct getter<two_things> {
|
||||||
|
static two_things get(lua_State* L, int index, record& tracking) {
|
||||||
|
// Get the first element
|
||||||
|
int a = stack::get<int>(L, index);
|
||||||
|
// Get the second element,
|
||||||
|
// in the +1 position from the first
|
||||||
|
bool b = stack::get<bool>(L, index + 1);
|
||||||
|
// we use 2 slots, each of the previous takes 1
|
||||||
|
tracking.use(2);
|
||||||
|
return two_things{ a, b };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct pusher<two_things> {
|
||||||
|
static int push(lua_State* L, const two_things& things) {
|
||||||
|
int amount = stack::push(L, things.a);
|
||||||
|
amount += stack::push(L, things.b);
|
||||||
|
// Return 2 things
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
// Create a pass-through style of function
|
||||||
|
lua.script("function f ( a, b ) return a, b end");
|
||||||
|
|
||||||
|
// get the function out of Lua
|
||||||
|
sol::function f = lua["f"];
|
||||||
|
|
||||||
|
two_things things = f(two_things{ 24, true });
|
||||||
|
// things.a == 24
|
||||||
|
// things.b == true
|
||||||
|
|
||||||
|
std::cout << "=== customization example ===" << std::endl;
|
||||||
|
std::cout << std::boolalpha;
|
||||||
|
std::cout << "things.a: " << things.a << std::endl;
|
||||||
|
std::cout << "things.b: " << things.b << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ inline std::string make_string( std::string input ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
std::cout << "=== functions example ===" << std::endl;
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base);
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ int main() {
|
||||||
lua.script("assert(mult_by_ten(50) == 500)");
|
lua.script("assert(mult_by_ten(50) == 500)");
|
||||||
lua.script("assert(mult_by_five(10) == 50)");
|
lua.script("assert(mult_by_five(10) == 50)");
|
||||||
|
|
||||||
// using lambdas, functions could have state.
|
// using lambdas, functions can have state.
|
||||||
int x = 0;
|
int x = 0;
|
||||||
lua.set_function("inc", [&x]() { x += 10; });
|
lua.set_function("inc", [&x]() { x += 10; });
|
||||||
|
|
||||||
|
@ -53,7 +55,11 @@ int main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// this can be done as many times as you want
|
// this can be done as many times as you want
|
||||||
lua.script("inc()\ninc()\ninc()");
|
lua.script(R"(
|
||||||
|
inc()
|
||||||
|
inc()
|
||||||
|
inc()
|
||||||
|
)");
|
||||||
assert(x == 40);
|
assert(x == 40);
|
||||||
if (x == 40) {
|
if (x == 40) {
|
||||||
// Do something based on this information
|
// Do something based on this information
|
||||||
|
@ -63,9 +69,11 @@ int main() {
|
||||||
// to other variables, using sol::function
|
// to other variables, using sol::function
|
||||||
sol::function add = lua["my_add"];
|
sol::function add = lua["my_add"];
|
||||||
int value = add(10, 11);
|
int value = add(10, 11);
|
||||||
assert(add.call<int>(10, 11) == 21);
|
// second way to call the function
|
||||||
|
int value2 = add.call<int>(10, 11);
|
||||||
assert(value == 21);
|
assert(value == 21);
|
||||||
if (value == 21) {
|
assert(value2 == 21);
|
||||||
|
if (value == 21 && value2 == 21) {
|
||||||
std::cout << "Woo, it's 21!" << std::endl;
|
std::cout << "Woo, it's 21!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +86,7 @@ int main() {
|
||||||
auto multi = lua.get<sol::function>("multi");
|
auto multi = lua.get<sol::function>("multi");
|
||||||
int first;
|
int first;
|
||||||
std::string second;
|
std::string second;
|
||||||
std::tie(first, second) = multi.call<int, std::string>();
|
sol::tie(first, second) = multi();
|
||||||
|
|
||||||
// use the values
|
// use the values
|
||||||
assert(first == 10);
|
assert(first == 10);
|
||||||
|
@ -97,4 +105,6 @@ print(func(1))
|
||||||
print(func("bark"))
|
print(func("bark"))
|
||||||
print(func(1,2))
|
print(func(1,2))
|
||||||
)");
|
)");
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
29
examples/player_script.lua
Normal file
29
examples/player_script.lua
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
-- call single argument integer constructor
|
||||||
|
p1 = player.new(2)
|
||||||
|
|
||||||
|
-- p2 is still here from being
|
||||||
|
-- set with lua["p2"] = player(0); below
|
||||||
|
local p2shoots = p2:shoot()
|
||||||
|
assert(not p2shoots)
|
||||||
|
-- had 0 ammo
|
||||||
|
|
||||||
|
-- set variable property setter
|
||||||
|
p1.hp = 545;
|
||||||
|
-- get variable through property getter
|
||||||
|
print(p1.hp);
|
||||||
|
|
||||||
|
local did_shoot_1 = p1:shoot()
|
||||||
|
print(did_shoot_1)
|
||||||
|
print(p1.bullets)
|
||||||
|
local did_shoot_2 = p1:shoot()
|
||||||
|
print(did_shoot_2)
|
||||||
|
print(p1.bullets)
|
||||||
|
local did_shoot_3 = p1:shoot()
|
||||||
|
print(did_shoot_3)
|
||||||
|
|
||||||
|
-- can read
|
||||||
|
print(p1.bullets)
|
||||||
|
-- would error: is a readonly variable, cannot write
|
||||||
|
-- p1.bullets = 20
|
||||||
|
|
||||||
|
p1:boost()
|
47
examples/protected_functions.cpp
Normal file
47
examples/protected_functions.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== protected_functions example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
// A complicated function which can error out
|
||||||
|
// We define both in terms of Lua code
|
||||||
|
|
||||||
|
lua.script(R"(
|
||||||
|
function handler (message)
|
||||||
|
return "Handled this message: " .. message
|
||||||
|
end
|
||||||
|
|
||||||
|
function f (a)
|
||||||
|
if a < 0 then
|
||||||
|
error("negative number detected")
|
||||||
|
end
|
||||||
|
return a + 5
|
||||||
|
end
|
||||||
|
)");
|
||||||
|
|
||||||
|
// Get a protected function out of Lua
|
||||||
|
sol::protected_function f = lua["f"];
|
||||||
|
// Set a non-default error handler
|
||||||
|
f.error_handler = lua["handler"];
|
||||||
|
|
||||||
|
sol::protected_function_result result = f(-500);
|
||||||
|
if (result.valid()) {
|
||||||
|
// Call succeeded
|
||||||
|
int x = result;
|
||||||
|
std::cout << x << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Call failed
|
||||||
|
sol::error err = result;
|
||||||
|
std::string what = err.what();
|
||||||
|
std::cout << what << std::endl;
|
||||||
|
// 'what' Should read
|
||||||
|
// "Handled this message: negative number detected"
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
54
examples/static_variables.cpp
Normal file
54
examples/static_variables.cpp
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct test {
|
||||||
|
static int muh_variable;
|
||||||
|
};
|
||||||
|
int test::muh_variable = 25;
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== static_variables example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries();
|
||||||
|
lua.new_usertype<test>("test",
|
||||||
|
"direct", sol::var(2),
|
||||||
|
"global", sol::var(test::muh_variable),
|
||||||
|
"ref_global", sol::var(std::ref(test::muh_variable))
|
||||||
|
);
|
||||||
|
|
||||||
|
int direct_value = lua["test"]["direct"];
|
||||||
|
std::cout << "direct_value: " << direct_value << std::endl;
|
||||||
|
// direct_value == 2
|
||||||
|
|
||||||
|
int global = lua["test"]["global"];
|
||||||
|
// global == 25
|
||||||
|
int global2 = lua["test"]["ref_global"];
|
||||||
|
// global2 == 25
|
||||||
|
|
||||||
|
std::cout << "First round of values --" << std::endl;
|
||||||
|
std::cout << global << std::endl;
|
||||||
|
std::cout << global2 << std::endl;
|
||||||
|
|
||||||
|
test::muh_variable = 542;
|
||||||
|
|
||||||
|
global = lua["test"]["global"];
|
||||||
|
// global == 25
|
||||||
|
// global is its own memory: was passed by value
|
||||||
|
|
||||||
|
global2 = lua["test"]["ref_global"];
|
||||||
|
// global2 == 542
|
||||||
|
// global2 was passed through std::ref
|
||||||
|
// global2 holds a reference to muh_variable
|
||||||
|
// if muh_variable goes out of scope or is deleted
|
||||||
|
// problems could arise, so be careful!
|
||||||
|
|
||||||
|
std::cout << "Second round of values --" << std::endl;
|
||||||
|
std::cout << "global : " << global << std::endl;
|
||||||
|
std::cout << "global2: " << global2 << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
// this example shows how to read data in from a lua table
|
// this example shows how to read data in from a lua table
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
std::cout << "=== tables example ===" << std::endl;
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
// table used as an array
|
// table used as an array
|
||||||
lua.script("table1 = {\"hello\", \"table\"}");
|
lua.script("table1 = {\"hello\", \"table\"}");
|
||||||
|
@ -52,4 +54,6 @@ int main() {
|
||||||
<< lua.get<sol::table>("table2").get<sol::table>("nestedTable").get<std::string>("key2")
|
<< lua.get<sol::table>("table2").get<sol::table>("nestedTable").get<std::string>("key2")
|
||||||
<< '\n';
|
<< '\n';
|
||||||
std::cout << "name of t2: " << t2.get<std::string>("name") << '\n';
|
std::cout << "name of t2: " << t2.get<std::string>("name") << '\n';
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ struct variables {
|
||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
std::cout << "=== usertype example ===" << std::endl;
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::math);
|
lua.open_libraries(sol::lib::base, sol::lib::math);
|
||||||
|
|
||||||
|
@ -101,4 +103,7 @@ int main() {
|
||||||
"vars.low_gravity = true\n"
|
"vars.low_gravity = true\n"
|
||||||
"local x = vars.low_gravity\n"
|
"local x = vars.low_gravity\n"
|
||||||
"assert(x)");
|
"assert(x)");
|
||||||
|
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
119
examples/usertype_advanced.cpp
Normal file
119
examples/usertype_advanced.cpp
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct player {
|
||||||
|
public:
|
||||||
|
int bullets;
|
||||||
|
int speed;
|
||||||
|
|
||||||
|
player()
|
||||||
|
: player(3, 100) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
player(int ammo)
|
||||||
|
: player(ammo, 100) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
player(int ammo, int hitpoints)
|
||||||
|
: bullets(ammo), hp(hitpoints) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void boost() {
|
||||||
|
speed += 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shoot() {
|
||||||
|
if (bullets < 1)
|
||||||
|
return false;
|
||||||
|
--bullets;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_hp(int value) {
|
||||||
|
hp = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_hp() const {
|
||||||
|
return hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int hp;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
// note that you can set a
|
||||||
|
// userdata before you register a usertype,
|
||||||
|
// and it will still carry
|
||||||
|
// the right metatable if you register it later
|
||||||
|
|
||||||
|
// set a variable "p2" of type "player" with 0 ammo
|
||||||
|
lua["p2"] = player(0);
|
||||||
|
|
||||||
|
// make usertype metatable
|
||||||
|
lua.new_usertype<player>("player",
|
||||||
|
|
||||||
|
// 3 constructors
|
||||||
|
sol::constructors<sol::types<>, sol::types<int>, sol::types<int, int>>(),
|
||||||
|
|
||||||
|
// typical member function that returns a variable
|
||||||
|
"shoot", &player::shoot,
|
||||||
|
// typical member function
|
||||||
|
"boost", &player::boost,
|
||||||
|
|
||||||
|
// gets or set the value using member variable syntax
|
||||||
|
"hp", sol::property(&player::get_hp, &player::set_hp),
|
||||||
|
|
||||||
|
// read and write variable
|
||||||
|
"speed", &player::speed,
|
||||||
|
// can only read from, not write to
|
||||||
|
"bullets", sol::readonly(&player::bullets)
|
||||||
|
);
|
||||||
|
|
||||||
|
std::string player_script = R"(
|
||||||
|
-- call single argument integer constructor
|
||||||
|
p1 = player.new(2)
|
||||||
|
|
||||||
|
-- p2 is still here from being
|
||||||
|
-- set with lua["p2"] = player(0); below
|
||||||
|
local p2shoots = p2:shoot()
|
||||||
|
assert(not p2shoots)
|
||||||
|
-- had 0 ammo
|
||||||
|
|
||||||
|
-- set variable property setter
|
||||||
|
p1.hp = 545;
|
||||||
|
-- get variable through property getter
|
||||||
|
print(p1.hp);
|
||||||
|
|
||||||
|
local did_shoot_1 = p1:shoot()
|
||||||
|
print(did_shoot_1)
|
||||||
|
print(p1.bullets)
|
||||||
|
local did_shoot_2 = p1:shoot()
|
||||||
|
print(did_shoot_2)
|
||||||
|
print(p1.bullets)
|
||||||
|
local did_shoot_3 = p1:shoot()
|
||||||
|
print(did_shoot_3)
|
||||||
|
|
||||||
|
-- can read
|
||||||
|
print(p1.bullets)
|
||||||
|
-- would error: is a readonly variable, cannot write
|
||||||
|
-- p1.bullets = 20
|
||||||
|
|
||||||
|
p1:boost()
|
||||||
|
)";
|
||||||
|
|
||||||
|
// Uncomment and use the file to try that out, too!
|
||||||
|
// Make sure it's in the local directory of the executable after you build, or adjust the filename path
|
||||||
|
// Or whatever else you like!
|
||||||
|
//lua.script_file("player_script.lua");
|
||||||
|
lua.script(player_script);
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
std::cout << "=== variables example ===" << std::endl;
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
|
|
||||||
// need the base library for assertions
|
// need the base library for assertions
|
||||||
|
@ -31,4 +33,5 @@ int main() {
|
||||||
std::cout << y << std::endl;
|
std::cout << y << std::endl;
|
||||||
std::cout << x2 << std::endl;
|
std::cout << x2 << std::endl;
|
||||||
std::cout << y2 << std::endl;
|
std::cout << y2 << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
37
examples/variadic_args.cpp
Normal file
37
examples/variadic_args.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== variadic_args example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
// Function requires 2 arguments
|
||||||
|
// rest can be variadic, but:
|
||||||
|
// va will include everything after "a" argument,
|
||||||
|
// which means "b" will be part of the varaidic_args list too
|
||||||
|
// at position 0
|
||||||
|
lua.set_function("v", [](int a, sol::variadic_args va, int /*b*/) {
|
||||||
|
int r = 0;
|
||||||
|
for (auto v : va) {
|
||||||
|
int value = v; // get argument out (implicit conversion)
|
||||||
|
// can also do int v = va.get<int>(i); with index i
|
||||||
|
r += value;
|
||||||
|
}
|
||||||
|
// Only have to add a, b was included from variadic_args and beyond
|
||||||
|
return r + a;
|
||||||
|
});
|
||||||
|
|
||||||
|
lua.script("x = v(25, 25)");
|
||||||
|
lua.script("x2 = v(25, 25, 100, 50, 250, 150)");
|
||||||
|
lua.script("x3 = v(1, 2, 3, 4, 5, 6)");
|
||||||
|
// will error: not enough arguments
|
||||||
|
//lua.script("x4 = v(1)");
|
||||||
|
|
||||||
|
lua.script("print(x)"); // 50
|
||||||
|
lua.script("print(x2)"); // 600
|
||||||
|
lua.script("print(x3)"); // 21
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
|
@ -1340,3 +1340,56 @@ t.global = 20
|
||||||
print(t.global)
|
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);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user