sol2
sol2 copied to clipboard
how to make lua multidimensional array like "temp_array[2][3]" in C++
Hi i am a huge fan of your solution, sol2. and i am adapting that solution on emscripten that make wasm.
but i cant find the way to make lua multidimensional array like lua_temp_array[2][3].
On C++, there is a array, int* temp_array. temp_array is 6 size, and temp_array value is 0,1,2,3,4,5. In this situation, how can bind this temp_array with lua_temp_array?
i know, sol2 offered many ways to use C++ container in lua script like vector, map, ..... and so on. but i just want to bind temp_array with lua_temp_array using sol2.
if sol2 wouldn't have solution to adapting this situation, then i would have no choice but to use just original lua not sol2
IDE : Visual Studio Code Language : C++ Compiler: Emscripten
Thanks.
Can you use std::span
for this? Create a std::span<std::span<int, 3>, 2>
which will point to the two arrays of three elements.
Then create a new usertype for this type, where the sol::meta_function::index
and sol::meta_function::new_index
functions will return and store a std::span<int, 3>
. Next, create a new usertype for std::span<int, 3>
. The index/new_index functions for this type will return and store an int
. This will give you working multi-dimensional indexing within Lua.
You might need to swap the dimensions to get row-major or column-major ordering to match the C array structure. I didn't think too hard about that when writing up this reply.
If you want to vary the dimension sizes at runtime, use the std::dynamic_extent
option when defining the specialised span type.
Example I've been working on today with the GLM library. Not exactly the same as std::span, but the logic here should be adaptable without much extra work.
namespace {
template<typename T, typename U>
auto fetchIndex(T const& c, typename T::length_type idx) -> U const& {
if (idx < c.length()) {
return c[idx];
} else {
throw std::logic_error("GLM index out of range");
}
}
template<typename T, typename U>
auto fetchIndex(T & c, typename T::length_type idx) -> U& {
if (idx < c.length()) {
return c[idx];
} else {
throw std::logic_error("GLM index out of range");
}
}
template<typename T, typename U>
auto storeIndex(T & c, typename T::length_type idx, U const& v) -> void {
if (idx < c.length()) {
c[idx] = v;
} else {
throw std::logic_error("GLM index out of range");
}
}
}
void luaGlmInit(sol::state& state)
{
state.new_usertype<glm::vec4>(
"vec4",
sol::constructors<glm::vec4(),
glm::vec4(float const&),
glm::vec4(float const&, float const&, float const&, float const&)>(),
sol::meta_function::multiplication, sol::resolve<glm::vec4 (glm::vec4 const&, glm::vec4 const&)>(&glm::operator*),
sol::meta_function::division, sol::resolve<glm::vec4 (glm::vec4 const&, glm::vec4 const&)>(&glm::operator/),
sol::meta_function::addition, sol::resolve<glm::vec4 (glm::vec4 const&, glm::vec4 const&)>(&glm::operator+),
sol::meta_function::subtraction, sol::resolve<glm::vec4 (glm::vec4 const&, glm::vec4 const&)>(&glm::operator-),
sol::meta_function::index, sol::resolve<const float& (glm::vec4 const&, glm::length_t)>(fetchIndex),
sol::meta_function::new_index, sol::resolve<void (glm::vec4&, glm::length_t, float const&)>(storeIndex)
);
state.new_usertype<glm::mat4>(
"mat4",
sol::constructors<glm::mat4(),
glm::mat4(float const&),
glm::mat4(float const&, float const&, float const&, float const&,
float const&, float const&, float const&, float const&,
float const&, float const&, float const&, float const&,
float const&, float const&, float const&, float const&)>(),
sol::meta_function::multiplication, sol::resolve<glm::mat4 (glm::mat4 const&, glm::mat4 const&)>(&glm::operator*),
sol::meta_function::addition, sol::resolve<glm::mat4 (glm::mat4 const&, glm::mat4 const&)>(&glm::operator+),
sol::meta_function::subtraction, sol::resolve<glm::mat4 (glm::mat4 const&, glm::mat4 const&)>(&glm::operator-),
sol::meta_function::index, sol::resolve<glm::vec4& (glm::mat4 &, glm::length_t)>(fetchIndex),
sol::meta_function::new_index, sol::resolve<void (glm::mat4&, glm::length_t, glm::vec4 const&)>(storeIndex)
);
}
Test code:
TEST_F(LuaGLM, ArrayIndexing)
{
lua->script(
"b=mat4.new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)\n"
"print(b)\n"
"print(\"b[0] = \" .. tostring(b[0]))\n"
"print(\"b[1] = \" .. tostring(b[1]))\n"
"print(\"b[2] = \" .. tostring(b[2]))\n"
"print(\"b[3] = \" .. tostring(b[3]))\n"
"print(b[3])\n"
"b[2][3] = 99.3\n"
"print(b)\n");
}
==>
mat4x4((1.000000, 2.000000, 3.000000, 4.000000), (5.000000, 6.000000, 7.000000, 8.000000), (9.000000, 10.000000, 11.000000, 12.000000), (13.000000, 14.000000, 15.000000, 16.000000))
b[0] = vec4(1.000000, 2.000000, 3.000000, 4.000000)
b[1] = vec4(5.000000, 6.000000, 7.000000, 8.000000)
b[2] = vec4(9.000000, 10.000000, 11.000000, 12.000000)
b[3] = vec4(13.000000, 14.000000, 15.000000, 16.000000)
vec4(13.000000, 14.000000, 15.000000, 16.000000)
mat4x4((1.000000, 2.000000, 3.000000, 4.000000), (5.000000, 6.000000, 7.000000, 8.000000), (9.000000, 10.000000, 11.000000, 99.300003), (13.000000, 14.000000, 15.000000, 16.000000))
it is a greate example. i pull off my problem thank to your kindness. I couldn’t have done it without you.