Pass parameters as reference from Lua to C++ -
i have lua function registered expects metatable parameter , want modify contents of table in c++ runtime:
int operate(lua_state *l) { std::vector<int> values{}; if (auto length = get_length_at_index(l, 1)) { result.reserve(length); lua_pushnil(l); while (lua_next(l, 1)) { result.push_back(lua_tointeger(l, -1)); lua_pop(l, 1); } } (auto &v : values) { v *= 2; } return 0; } int main() { auto l = lual_newstate(); lual_dofile(l, "script.lua"); lua_register(l, "operate", operate); return 0; }
the code above reads "lua.script"
looks this:
values = {1, 2, 3, 4, 5, 6} operate(values) index = 1, #values print(values[index]) end
the expected output values 1 6 multiplied 2, output unmodified values. obvious happens because i'm copying metatable std::vector
, modify copy.
is there way operate c++ runtime on lua objects in way reflect changes applied c++?
ps: know can return table function return value, want know if there's other options.
edit: didn't see knew why. explanation has been moved bottom future readers.
after first loop, table remains on top of stack, simplifying following solution. replace second loop with:
int count = int(result.size()); (int = 0; < count; ++i) { lua_pushinteger(l, result[i] * 2); lua_rawseti(l, -2, i); }
-2 refers lua value below top of stack(similarly, -1 refers top). when rawseti
reached lua stack looks like:
[-1]: copy of result[i]
[-2]: values
table
rawseti
pops value off top of stack , stores in specified table , index, making table top of stack again.
note can in fact within first loop, should avoid making habit of because lua operations cause undefined behavior while iterating, , further complicates code. see this post clarification.
why happen?
in summary, code writes c++ memory, not lua table.
the first loop iterates, reading each value , adding result
container.
lua_pushnil(l); while (lua_next(l, 1)) { result.push_back(lua_tointeger(l, -1)); lua_pop(l, 1); }
the second loop doubles value of each element within c++ container.
for (auto &v : values) { v *= 2; }
Comments
Post a Comment