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 2 3 4 5 6 7 8 9 10 11 12 13 14 | #define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <vector>
int main (int, char*[]) {
sol::state lua;
lua.open_libraries();
lua.set("my_table", sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5 }));
lua.script("for k, v in ipairs(my_table) do print(k, v) assert(k == v) end");
return 0;
}
|
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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
#include <vector>
#include <map>
#include "assert.hpp"
#include <iostream>
// This second demo is equivalent to the first
// Nota bene the signature here
// Every container-type that's meant to be
// a table must be wrapped in `sol::as_table_t`
// it's verbose, so feel free to use typedefs to make it easy on you
// you can mix which parts are considered tables from Lua, and which parts
// are considered other kinds of types, such as userdata and the like
void demo_explicit (sol::as_table_t<std::map<std::string, sol::as_table_t<std::vector<std::string>>>> src) {
std::cout << "demo, explicit sol::as_table_t<...>" << std::endl;
// Have to access the "source" member variable for as_table_t
const auto& listmap = src.value();
c_assert(listmap.size() == 2);
for (const auto& kvp : listmap) {
// Have to access the internal "source" for the inner as_table_t, as well
const std::vector<std::string>& strings = kvp.second.value();
c_assert(strings.size() == 3);
std::cout << "\t" << kvp.first << " = ";
for (const auto& s : strings) {
std::cout << "'" << s << "'" << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main(int, char**) {
std::cout << "=== containers retrieved from lua tables ===" << std::endl;
sol::state lua;
// bind the function
lua.set_function("g", &demo_explicit);
// Call it with a table that has string sequences set to distinct keys
lua.script(R"(
t = {
key1 = {'hello', 'there', 'world'},
key2 = {'bark', 'borf', 'woof'}
}
g(t)
)");
std::cout << std::endl;
return 0;
}
|