Update teh docs, woooo.

This commit is contained in:
ThePhD 2016-11-04 19:41:16 -04:00
parent d863a56760
commit d1c203b0c5
7 changed files with 185 additions and 75 deletions

View File

@ -48,9 +48,9 @@ More examples are given in the examples directory.
## Presentations
"A Sun For the Moon - A Zero-Overhead Lua Abstraction using C++"
ThePhD
Lua Workshop 2016 - Mashape, San Francisco, CA
"A Sun For the Moon - A Zero-Overhead Lua Abstraction using C++"
ThePhD
Lua Workshop 2016 - Mashape, San Francisco, CA
[Deck](https://github.com/ThePhD/sol2/blob/develop/docs/presentations/ThePhD%20-%20No%20Overhead%20C%20Abstraction%20-%202016.10.14.pdf)
## Creating a single header

View File

@ -23,4 +23,6 @@ This function serves the purpose of ensuring that an object is pushed -- if poss
Note that any caveats with Lua tables apply the moment it is serialized, and the data cannot be gotten out back out in C++ as a C++ type without explicitly using the ``as_table_t`` marker for your get and conversion operations using Sol.
If you need this functionality with a member variable, use a :doc:`property on a getter function<property>` that returns the result of ``sol::as_table``.
This marker does NOT apply to :doc:`usertypes<usertype>`.

View File

@ -0,0 +1,72 @@
containers
==========
for handling ``std::vector/map`` and others
-------------------------------------------
Sol2 automatically converts containers (detected using the ``sol::is_container<T>`` type trait, which simply looks for begin / end) to be a special kind of userdata with metatable on it. For Lua 5.2 and 5.3, this is extremely helpful as you can make typical containers behave like Lua tables without losing the actual container that they came from, as well as a small amount of indexing and other operations that behave properly given the table type.
Here's a complete working example of it working for Lua 5.3 and Lua 5.2, and how you can retrieve out the container in all versions:
.. code-block:: cpp
:caption: containers.cpp
#define SOL_CHECK_ARGUMENTS
#include <sol.hpp>
int main() {
sol::state lua;
lua.open_libraries();
lua.script(R"(
function f (x)
print('--- Calling f ---')
for k, v in ipairs(x) do
print(k, v)
end
end
)");
// Have the function we
// just defined in Lua
sol::function f = lua["f"];
// Set a global variable called
// "arr" to be a vector of 5 lements
lua["arr"] = std::vector<int>{ 2, 4, 6, 8, 10 };
// Call it, see 5 elements
// printed out
f(lua["arr"]);
// Mess with it in C++
std::vector<int>& reference_to_arr = lua["arr"];
reference_to_arr.push_back(12);
// Call it, see *6* elements
// printed out
f(lua["arr"]);
return 0;
}
Note that this will not work well in 5.1, as it has explicit table checks and does not check metamethods, even when ``pairs`` or ``ipairs`` is passed a table. In that case, you will need to use a more manual iteration scheme.
If you have a type that has ``begin`` or ``end`` member functions but don't provide iterators, you can specialize ``sol::is_container<T>`` to be ``std::false_type``, and that will treat the type as a regular usertype and push it as a regular userdata:
.. code-block:: cpp
:caption: specialization.hpp
struct not_container {
void begin() {
}
void end() {
}
};
namespace sol {
template <>
struct is_container<not_container> : std::false_type {};
}

View File

@ -3,6 +3,10 @@ function
calling functions bound to Lua
------------------------------
.. note::
This abstraction assumes the function runs safely. If you expect your code to have errors (e.g., you don't always have explicit control over it or are trying to debug errors), please use :doc:`sol::protected_function<protected_function>`.
.. code-block:: cpp
class function : public reference;

View File

@ -82,6 +82,16 @@ Thanks to `Eric (EToreo) for the suggestion on this one`_!
These functions *load* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It will not run: it returns a ``load_result`` proxy that can be called to actually run the code, turned into a ``sol::function``, a ``sol::protected_function``, or some other abstraction. If it is called, it will run on the object's current ``lua_State*``: it is not isolated. If you need isolation, consider creating a new state or traditional Lua sandboxing techniques.
.. code-block:: cpp
:caption: function: do_string / do_file
:name: state-do-code
sol::protected_function_result do_string(const std::string& code);
sol::protected_function_result do_file(const std::string& filename);
These functions *loads and performs* the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``. It *will* run and returns a ``protected_function_result`` proxy that can be called to actually run the code, turned into a ``sol::function``, a ``sol::protected_function``, or some other abstraction.
.. code-block:: cpp
:caption: function: global table / registry table

View File

@ -47,6 +47,10 @@ running lua code
int value = lua.script("return 54");
// value == 54
To check the success of a loading operation:
.. code-block:: cpp
// load file without execute
sol::load_result script1 = lua.load_file("path/to/luascript.lua");
script1(); //execute
@ -59,6 +63,24 @@ running lua code
// value2 == 24
To check whether a script was successfully run or not (after loading is assumed to be successful):
.. code-block:: cpp
// execute and return result
sol::protected_function_result result1 = lua.do_string("return 24");
if (result1.valid()) {
int value = result1;
// value == 24
// yay!
}
else {
// ahhh :c
}
There is also ``lua.do_file("path/to/luascript.lua");``.
set and get variables
---------------------

144
tests.cpp
View File

@ -718,77 +718,77 @@ TEST_CASE("numbers/integers", "make sure integers are detectable on most platfor
}
TEST_CASE("state/script-returns", "make sure script returns are done properly") {
std::string script =
R"(
local example =
{
str = "this is a string",
num = 1234,
func = function(self)
print(self.str)
return "fstr"
end
}
return example;
)";
auto bar = [&script](sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.script(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto foo = [&script](int, sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.script(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto bar2 = [&script](sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.do_string(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto foo2 = [&script](int, sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.do_string(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
sol::state lua;
lua.open_libraries();
lua.set_function("foo", foo);
lua.set_function("foo2", foo2);
lua.set_function("bar", bar);
lua.set_function("bar2", bar2);
std::string script =
R"(
local example =
{
str = "this is a string",
num = 1234,
func = function(self)
print(self.str)
return "fstr"
end
}
return example;
)";
auto bar = [&script](sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.script(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto foo = [&script](int, sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.script(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto bar2 = [&script](sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.do_string(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
auto foo2 = [&script](int, sol::this_state l) {
sol::state_view lua = l;
sol::table data = lua.do_string(script);
std::string str = data["str"];
int num = data["num"];
std::string fstr = data["func"](data);
REQUIRE(str == "this is a string");
REQUIRE(fstr == "fstr");
REQUIRE(num == 1234);
};
sol::state lua;
lua.open_libraries();
lua.set_function("foo", foo);
lua.set_function("foo2", foo2);
lua.set_function("bar", bar);
lua.set_function("bar2", bar2);
lua.script("bar() bar2() foo(1) foo2(1)");
}