update examples and documentation, proof typing for user

This commit is contained in:
ThePhD 2017-08-24 14:57:28 -04:00
parent 92a6fb8c11
commit d98155cd22
6 changed files with 38 additions and 41 deletions

View File

@ -19,6 +19,7 @@ The examples folder also has a number of really great examples for you to see. T
- If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object - If you need dynamic callbacks or runtime overridable functions, have a ``std::function`` member variable and get/set it on the usertype object
- ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``) - ``std::function`` works as a member variable or in passing as an argument / returning as a value (you can even use it with ``sol::property``)
- You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details - You can also create an entirely dynamic object: see the `dynamic_object example`_ for more details
* (Advanced) You can override the iteration function for Lua 5.2 and above (LuaJIT not included) `as shown in the pairs example`_
* You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return * You can use :doc:`filters<api/filters>` to control dependencies and streamline return values, as well as apply custom behavior to a functions return
* Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods * Please note that the colon is necessary to "automatically" pass the ``this``/``self`` argument to Lua methods
- ``obj:method_name()`` is how you call "member" methods in Lua - ``obj:method_name()`` is how you call "member" methods in Lua
@ -52,3 +53,4 @@ The examples folder also has a number of really great examples for you to see. T
.. _C++: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp#L51 .. _C++: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_simple.cpp#L51
.. _Certain operators: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_automatic_operators.cpp .. _Certain operators: https://github.com/ThePhD/sol2/blob/develop/examples/usertype_automatic_operators.cpp
.. _dynamic_object example: https://github.com/ThePhD/sol2/blob/develop/examples/dynamic_object.cpp .. _dynamic_object example: https://github.com/ThePhD/sol2/blob/develop/examples/dynamic_object.cpp
.. _as shown in this example: https://github.com/ThePhD/sol2/blob/develop/examples/pairs.cpp

View File

@ -21,9 +21,8 @@ struct lua_iterator_state {
typedef std::map<std::string, int>::iterator it_t; typedef std::map<std::string, int>::iterator it_t;
it_t it; it_t it;
it_t last; it_t last;
std::reference_wrapper<my_thing> source;
lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {} lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()) {}
}; };
std::tuple<sol::object, sol::object> my_next(sol::user<lua_iterator_state&> user_it_state, sol::this_state l) { std::tuple<sol::object, sol::object> my_next(sol::user<lua_iterator_state&> user_it_state, sol::this_state l) {
@ -35,7 +34,6 @@ std::tuple<sol::object, sol::object> my_next(sol::user<lua_iterator_state&> user
// the key value is argument 2, but we do not // the key value is argument 2, but we do not
// care about the key value here // care about the key value here
lua_iterator_state& it_state = user_it_state; lua_iterator_state& it_state = user_it_state;
my_thing& source = it_state.source;
auto& it = it_state.it; auto& it = it_state.it;
if (it == it_state.last) { if (it == it_state.last) {
// return nil to signify that // return nil to signify that
@ -53,7 +51,7 @@ std::tuple<sol::object, sol::object> my_next(sol::user<lua_iterator_state&> user
// the iterator must be moved forward one before we return // the iterator must be moved forward one before we return
std::advance(it, 1); std::advance(it, 1);
return r; return r;
}; }
auto my_pairs(my_thing& mt) { auto my_pairs(my_thing& mt) {
// pairs expects 3 returns: // pairs expects 3 returns:
@ -67,11 +65,9 @@ auto my_pairs(my_thing& mt) {
// it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup // it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup
// saves space allocation and a single dereference // saves space allocation and a single dereference
return std::make_tuple(&my_next, sol::user<lua_iterator_state>(std::move(it_state)), sol::lua_nil); return std::make_tuple(&my_next, sol::user<lua_iterator_state>(std::move(it_state)), sol::lua_nil);
}; }
int main(int, char*[]) {
int main(int argc, char* argv[]) {
std::cout << "===== pairs (advanced) =====" << std::endl; std::cout << "===== pairs (advanced) =====" << std::endl;
sol::state lua; sol::state lua;

View File

@ -21,9 +21,8 @@ struct lua_iterator_state {
typedef std::map<std::string, int>::iterator it_t; typedef std::map<std::string, int>::iterator it_t;
it_t it; it_t it;
it_t last; it_t last;
std::reference_wrapper<my_thing> source;
lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()), source(mt) {} lua_iterator_state(my_thing& mt) : it(mt.m.begin()), last(mt.m.end()) {}
}; };
int my_next(lua_State* L) { int my_next(lua_State* L) {
@ -34,7 +33,6 @@ int my_next(lua_State* L) {
// the key value is argument 2 // the key value is argument 2
// we do not care about the key value here // we do not care about the key value here
lua_iterator_state& it_state = sol::stack::get<sol::user<lua_iterator_state>>(L, 1); lua_iterator_state& it_state = sol::stack::get<sol::user<lua_iterator_state>>(L, 1);
my_thing& source = it_state.source;
auto& it = it_state.it; auto& it = it_state.it;
if (it == it_state.last) { if (it == it_state.last) {
return sol::stack::push(L, sol::lua_nil); return sol::stack::push(L, sol::lua_nil);
@ -47,16 +45,7 @@ int my_next(lua_State* L) {
pushed += sol::stack::push_reference(L, itderef.second); pushed += sol::stack::push_reference(L, itderef.second);
std::advance(it, 1); std::advance(it, 1);
return pushed; return pushed;
}; }
auto my_pairs(my_thing& mt) {
// prepare our state
lua_iterator_state it_state(mt);
return std::make_tuple(&my_next, sol::user<lua_iterator_state>(std::move(it_state)), sol::lua_nil);
// sol::user above is a space/time optimization over regular usertypes,
// it's incompatible with regular usertypes and stores the type T directly in lua without any pretty setup
// saves space allocation and a single dereference
};
int my_pairs(lua_State* L) { int my_pairs(lua_State* L) {
my_thing& mt = sol::stack::get<my_thing>(L, 1); my_thing& mt = sol::stack::get<my_thing>(L, 1);
@ -71,16 +60,16 @@ int my_pairs(lua_State* L) {
pushed += sol::stack::push<sol::user<lua_iterator_state>>(L, std::move(it_state)); pushed += sol::stack::push<sol::user<lua_iterator_state>>(L, std::move(it_state));
pushed += sol::stack::push(L, sol::lua_nil); pushed += sol::stack::push(L, sol::lua_nil);
return pushed; return pushed;
}; }
int main(int argc, char* argv[]) { int main(int, char*[]) {
std::cout << "===== pairs (using raw Lua C functions) (advanced) =====" << std::endl; std::cout << "===== pairs (using raw Lua C functions) (advanced) =====" << std::endl;
sol::state lua; sol::state lua;
lua.open_libraries(sol::lib::base); lua.open_libraries(sol::lib::base);
lua.new_usertype<my_thing>("my_thing", lua.new_usertype<my_thing>("my_thing",
sol::meta_function::pairs, my_pairs sol::meta_function::pairs, &my_pairs
); );
lua.safe_script(R"( lua.safe_script(R"(

View File

@ -79,10 +79,19 @@ print("obj1:", obj1)
print("obj2:", obj2) print("obj2:", obj2)
print("obj3:", obj2) print("obj3:", obj2)
print("#obj1:", #obj1)
print("#obj2:", #obj2)
print("#obj3:", #obj3)
obj1() obj1() obj1() obj1() obj1() obj1() obj1() obj1() obj1() obj1() obj1() obj1()
obj2() obj2() obj2() obj2() obj2() obj2()
obj3() obj3() obj3() obj3() obj3() obj3()
print("after modifications using obj() operator")
print("obj1:", obj1)
print("obj2:", obj2)
print("obj3:", obj2)
print("#obj1:", #obj1) print("#obj1:", #obj1)
print("#obj2:", #obj2) print("#obj2:", #obj2)
print("#obj3:", #obj3) print("#obj3:", #obj3)
@ -100,14 +109,15 @@ end
print("obj1 == obj2:", obj1 == obj2) print("obj1 == obj2:", obj1 == obj2)
print("obj1 < obj2:", obj1 < obj2) print("obj1 < obj2:", obj1 < obj2)
print("obj1 >= obj2:", obj1 >= obj2) print("obj1 >= obj2:", obj1 >= obj2)
assert(obj1 ~= obj2)
assert(obj1 > obj2)
assert(obj1 >= obj2)
print("obj2 == obj3:", obj1 == obj2) print("obj2 == obj3:", obj2 == obj3)
print("obj2 > obj3:", obj1 > obj2) print("obj2 > obj3:", obj2 > obj3)
print("obj2 <= obj3:", obj1 <= obj2) print("obj2 <= obj3:", obj2 <= obj3)
assert(obj2 == obj3)
print("obj1:", obj1) assert(obj2 <= obj3)
print("obj2:", obj2)
print("obj3:", obj2)
)"); )");
std::cout << std::endl; std::cout << std::endl;

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2017-08-24 18:37:55.297938 UTC // Generated 2017-08-24 18:56:19.661582 UTC
// This header was generated with sol v2.18.1 (revision a163ae7) // This header was generated with sol v2.18.0 (revision 92a6fb8)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -4225,10 +4225,10 @@ namespace sol {
struct user { struct user {
U value; U value;
user(U x) : value(std::move(x)) {} user(U x) : value(std::forward<U>(x)) {}
operator std::remove_reference_t<U>* () { return std::addressof(value); } operator std::add_pointer_t<std::remove_reference_t<U>> () { return std::addressof(value); }
operator U& () { return value; } operator std::add_lvalue_reference_t<U> () { return value; }
operator const U& () const { return value; } operator std::add_const_t<std::add_lvalue_reference_t<U>>& () const { return value; }
}; };
template <typename T> template <typename T>

View File

@ -324,10 +324,10 @@ namespace sol {
struct user { struct user {
U value; U value;
user(U x) : value(std::move(x)) {} user(U x) : value(std::forward<U>(x)) {}
operator std::remove_reference_t<U>* () { return std::addressof(value); } operator std::add_pointer_t<std::remove_reference_t<U>> () { return std::addressof(value); }
operator U& () { return value; } operator std::add_lvalue_reference_t<U> () { return value; }
operator const U& () const { return value; } operator std::add_const_t<std::add_lvalue_reference_t<U>>& () const { return value; }
}; };
template <typename T> template <typename T>