mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
73 lines
2.1 KiB
ReStructuredText
73 lines
2.1 KiB
ReStructuredText
|
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 {};
|
||
|
}
|