as_table¶
make sure an object is pushed as a table
template <typename T>
as_table_t {
T& value() &;
const T& value() & const;
T&& value() &&;
};
template <typename T>
as_table_t<T> as_function ( T&& container );
This function serves the purpose of ensuring that an object is pushed – if possible – like a table into Lua. The container passed here can be a pointer, a reference, a std::reference_wrapper around a container, or just a plain container value. It must have a begin/end function, and if it has a std::pair<Key, Value> as its value_type, it will be pushed as a dictionary. Otherwise, it’s pushed as a sequence.
1#define SOL_ALL_SAFETIES_ON 1
2#include <sol/sol.hpp>
3
4#include <vector>
5
6int main(int, char*[]) {
7
8 sol::state lua;
9 lua.open_libraries();
10 lua.set("my_table",
11 sol::as_table(std::vector<int> { 1, 2, 3, 4, 5 }));
12 lua.script(
13 "for k, v in ipairs(my_table) do print(k, v) assert(k "
14 "== v) end");
15
16 return 0;
17}
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. You can deserialize the Lua table into something explicitly using the sol::as_table_t marker for your get and conversion operations using sol. At that point, the returned type is deserialized from a table, meaning you cannot reference any kind of C++ data directly as you do with regular userdata/usertypes. All C++ type information is lost upon serialization into Lua.
If you need this functionality with a member variable, use a property on a getter function that returns the result of sol::as_table.
This marker does NOT apply to usertypes.
You can also use this to nest types and retrieve tables within tables as shown by this example.
1#define SOL_ALL_SAFETIES_ON 1
2#include <sol/sol.hpp>
3
4#include <vector>
5#include <map>
6#include <iostream>
7
8
9}
10
11// This second demo is equivalent to the first
12// Nota bene the signature here
13// Every container-type that's meant to be
14// a table must be wrapped in `sol::as_table_t`
15// it's verbose, so feel free to use typedefs to make it easy on
16// you you can mix which parts are considered tables from Lua,
17// and which parts are considered other kinds of types, such as
18// userdata and the like
19void demo_explicit(sol::as_table_t<std::map<std::string,
20 sol::as_table_t<std::vector<std::string>>>>
21 src) {
22 std::cout << "demo, explicit sol::as_table_t<...>"
23 << std::endl;
24 // Have to access the "source" member variable for
25 // as_table_t
26 const auto& listmap = src.value();
27 SOL_ASSERT(listmap.size() == 2);
28 for (const auto& kvp : listmap) {
29 // Have to access the internal "source" for the inner
30 // as_table_t, as well
31 const std::vector<std::string>& strings
32 = kvp.second.value();
33 SOL_ASSERT(strings.size() == 3);
34 std::cout << "\t" << kvp.first << " = ";
35 for (const auto& s : strings) {
36 std::cout << "'" << s << "'"
37 << " ";
38 }
39 }
40 std::cout << std::endl;
41}
42
43int main(int, char**) {
44 std::cout << "=== containers retrieved from lua tables ==="
45 << std::endl;
46 sol::state lua;
47 // bind the function
48 lua.set_function("f", &demo);
49 lua.set_function("g", &demo_explicit);
50 // Call it with a table that has string sequences set to
51 // distinct keys
52 lua.script(R"(
53t = {
54 key1 = {'hello', 'there', 'world'},
55 key2 = {'bark', 'borf', 'woof'}
56}
57f(t)
58g(t)
59 )");
60
61 std::cout << std::endl;
62
63 return 0;
64}