sol2 icon indicating copy to clipboard operation
sol2 copied to clipboard

A const C++ container can be modified in Lua (want it to be truly const)

Open totalgee opened this issue 1 year ago • 0 comments

I'd like to expose a const container (here it happens to be a std::vector) to Lua via Sol, so it can be iterated/accessed there but not modified. I thought that exposing a const ref to the thing (rather than a ref) would prevent modifications to it via Lua, but there is no error when I try to add elements in various ways; I actually manage to modify the "const" declared C++ vector!

Compiler: Visual Studio 2022, C++17 or C++20 OS: Windows 11 Pro

Here is an example that shows the problem, and what I'm trying to do. It's basically a slightly modified version of your example from the documentation, but where I tried to make the vector constant:

#include "sol/sol.hpp"

int main() {
    sol::state lua;
    lua.open_libraries(sol::lib::base, sol::lib::package, sol::lib::os, sol::lib::string);

    lua.script(R"lua(
function printContainer(x)
	print("\ncontainer has:")
	for k = 1, #x do
		v = tostring(x[k])
		print("\t", k, v)
	end
end
	)lua");

    sol::function printContainer = lua["printContainer"];

    // Expose a constant vector to Lua
    // (first tried exposing as a cref, and then I even tried setting the underlying variable as const!)
    auto const arr = std::vector<int>{ 2, 4, 6, 8, 10 };
    lua["arr"] = std::cref(arr);
    printContainer(lua["arr"]);
    std::cout << "Size of C++ arr: " << arr.size() << '\n';

    // Presumably we shouldn't be able to get a non-const reference to it...?
    std::vector<int>& reference_to_arr = lua["arr"];
    reference_to_arr.push_back(12);

    // See *6* elements printed out (but it's supposed to be const)
    printContainer(lua["arr"]);
    std::cout << "Size of C++ arr: " << arr.size() << '\n';

    // Modify it from Lua
    lua.script(R"(
arr:add(28)
	)");

    // See *7* elements printed out (again, it's intended to be const)
    printContainer(lua["arr"]);
    std::cout << "Size of C++ arr: " << arr.size() << '\n';

    return 0;
}

The program outputs:

container has:
                1       2
                2       4
                3       6
                4       8
                5       10
Size of C++ arr: 5

container has:
                1       2
                2       4
                3       6
                4       8
                5       10
                6       12
Size of C++ arr: 6

container has:
                1       2
                2       4
                3       6
                4       8
                5       10
                6       12
                7       28
Size of C++ arr: 7

Ideally, I'd like to have the exposing as const "just work", but I guess it may be necessary to create my own container type...? I would expect it to give an error if I try to modify it. Maybe something like what happens if I use a const variable in Lua and then try to change it:

local x <const> = 3
x = 7

Which produces:

[sol2] An error occurred and has been passed to an error handler: sol: syntax error: [string "..."]:3: attempt to assign to const variable 'x'

totalgee avatar Mar 06 '24 23:03 totalgee