Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to make lua multidimensional array like "temp_array[2][3]" in C++ #1405

Open
dotori1995-enu opened this issue Sep 16, 2022 · 2 comments
Open

Comments

@dotori1995-enu
Copy link

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.

@rleigh-codelibre
Copy link

rleigh-codelibre commented Sep 18, 2022

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))

@dotori1995-enu
Copy link
Author

it is a greate example.
i pull off my problem thank to your kindness.
I couldn’t have done it without you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants