mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
add dynamic_object example
add note to functions about lambda return types
This commit is contained in:
parent
50a646de48
commit
a163ae7b33
|
@ -31,12 +31,48 @@ working with callables/lambdas
|
||||||
|
|
||||||
To be explicit about wanting a struct to be interpreted as a function, use ``mytable.set_function( key, func_value );``. You can be explicit about wanting a function as well by using the :doc:`sol::as_function<../api/as_function>` call, which will wrap and identify your type as a function.
|
To be explicit about wanting a struct to be interpreted as a function, use ``mytable.set_function( key, func_value );``. You can be explicit about wanting a function as well by using the :doc:`sol::as_function<../api/as_function>` call, which will wrap and identify your type as a function.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
As of sol 2.18.1, the below
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Function objects ``obj`` -- a struct with a ``return_type operator()( ... )`` member defined on them, like all C++ lambdas -- are not interpreted as functions when you use ``set`` for ``mytable.set( key, value )`` and ``state.create_table(_with)( ... )``. This only happens automagically with ``mytable[key] = obj``.
|
Function objects ``obj`` -- a struct with a ``return_type operator()( ... )`` member defined on them, like all C++ lambdas -- are not interpreted as functions when you use ``set`` for ``mytable.set( key, value )`` and ``state.create_table(_with)( ... )``. This only happens automagically with ``mytable[key] = obj``.
|
||||||
|
|
||||||
Note that this also applies to calling functions, for example: ``my_state["table"]["sort"]( some_table, sorting_object );``.
|
Note that this also applies to calling functions, for example: ``my_state["table"]["sort"]( some_table, sorting_object );``.
|
||||||
|
|
||||||
|
Furthermore, it is important to know that lambdas without a specified return type (and a non-const, non-reference-qualified ``auto``) will decay return values. To capture or return references explicitly, use ``decltype(auto)`` or specify the return type **exactly** as desired::
|
||||||
|
|
||||||
|
#define SOL_CHECK_ARGUMENTS 1
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
|
struct test {
|
||||||
|
int blah = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
test t;
|
||||||
|
sol::state lua;
|
||||||
|
lua.set_function("f", [&t]() {
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
lua.set_function("g", [&t]() -> test& {
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
lua.script("t1 = f()");
|
||||||
|
lua.script("t2 = g()");
|
||||||
|
|
||||||
|
test& lt1 = lua["t1"];
|
||||||
|
test& lt2 = lua["t2"];
|
||||||
|
|
||||||
|
assert(<1 != &t); // not the same: 'f' lambda copied
|
||||||
|
assert(<2 == &t); // the same: 'g' lambda returned reference
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
.. _function-exception-handling:
|
.. _function-exception-handling:
|
||||||
|
|
||||||
exception safety/handling
|
exception safety/handling
|
||||||
|
|
84
examples/dynamic_object.cpp
Normal file
84
examples/dynamic_object.cpp
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
#define SOL_CHECK_ARGUMENTS
|
||||||
|
#include <sol.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// use as-is,
|
||||||
|
// add as a member of your class,
|
||||||
|
// or derive from it and bind it appropriately
|
||||||
|
struct dynamic_object {
|
||||||
|
std::unordered_map<std::string, sol::object> entries;
|
||||||
|
|
||||||
|
void dynamic_set(std::string key, sol::stack_object value) {
|
||||||
|
auto it = entries.find(key);
|
||||||
|
if (it == entries.cend()) {
|
||||||
|
entries.insert(it, { std::move(key), std::move(value) });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::pair<const std::string, sol::object>& kvp = *it;
|
||||||
|
sol::object& entry = kvp.second;
|
||||||
|
entry = sol::object(std::move(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::object dynamic_get(std::string key) {
|
||||||
|
auto it = entries.find(key);
|
||||||
|
if (it == entries.cend()) {
|
||||||
|
return sol::lua_nil;
|
||||||
|
}
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cout << "=== dynamic_object example ===" << std::endl;
|
||||||
|
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
lua.new_usertype<dynamic_object>("dynamic_object",
|
||||||
|
sol::meta_function::index, &dynamic_object::dynamic_get,
|
||||||
|
sol::meta_function::new_index, &dynamic_object::dynamic_set,
|
||||||
|
sol::meta_function::length, [](dynamic_object& d) {
|
||||||
|
return d.entries.size();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
lua.safe_script(R"(
|
||||||
|
d1 = dynamic_object.new()
|
||||||
|
d2 = dynamic_object.new()
|
||||||
|
|
||||||
|
print(#d1) -- length operator
|
||||||
|
print(#d2)
|
||||||
|
|
||||||
|
function d2:run(lim)
|
||||||
|
local r = 0
|
||||||
|
for i=0,lim do
|
||||||
|
r = r + i
|
||||||
|
end
|
||||||
|
if (r % 2) == 1 then
|
||||||
|
print("odd")
|
||||||
|
end
|
||||||
|
return r
|
||||||
|
end
|
||||||
|
|
||||||
|
-- only added an entry to d2
|
||||||
|
print(#d1)
|
||||||
|
print(#d2)
|
||||||
|
|
||||||
|
-- only works on d2
|
||||||
|
local value = d2:run(5)
|
||||||
|
assert(value == 15)
|
||||||
|
)");
|
||||||
|
|
||||||
|
// does not work on d1: 'run' wasn't added to d1, only d2
|
||||||
|
auto script_result = lua.safe_script("local value = d1:run(5)", sol::script_pass_on_error);
|
||||||
|
assert(!script_result.valid());
|
||||||
|
sol::error err = script_result;
|
||||||
|
std::cout << "received error: " << err.what() << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user