c++ - 使用 C API 覆盖 Lua 中的赋值运算符

标签 c++ c lua variable-assignment metatable

我在我的 C++ 程序中有对象作为用户数据传递给 Lua,我重写了这个用户数据的元表,以便对对象的索引进行赋值(通过 __newindex 和 __index)导致对 C 的调用,这转换赋值以影响 C++ 对象或将 C++ 元素转换为 Lua 值(另一个用户数据或基本类型,如 bool、number、string)。用户数据作为参数传递给从我的 C++ 程序调用的类似事件的 Lua 函数。

luaL_newmetatable(L, "object");
lua_pushstring(L, "__index");
lua_pushvalue(L, -2);  /* pushes the metatable */
lua_settable(L, -3);  /* metatable.__index = metatable */

luaL_openlib(L, NULL, vallib_m, 0);
luaL_openlib(L, "internal", vallib_f, 0);

lua_pushstring(L, "__index");
lua_pushstring(L, "get");
lua_gettable(L, 2);  /* get val.get */
lua_settable(L, 1);  /* metatable.__index = val.get */

lua_pushstring(L, "__newindex");
lua_pushstring(L, "set");
lua_gettable(L, 2); /* get array.set */
lua_settable(L, 1); /* metatable.__newindex = val.set */

但是,这不允许我分配实际变量本身,只能分配变量的索引。没有直接覆盖赋值运算符的元事件,所以我正在寻找解决方法。

换句话说,我可以这样做:lua_userdata_object_passed_as_arg_to_event["is_it_true"]=true 并将 Lua bool 值分配给我的内部 C++ 对象,但如果我这样做: lua_userdata_object_passed_as_arg_to_event = new_object() 它会改变 Lua 变量引用的内容,但据我所知,它不会对核心对象做任何事情。

我考虑过的一种解决方法是一些 hack 要求开发人员执行 lua_userdata_object_passed_as_arg_to_event["__self"] = new_object() 如果他们想要更改对象本身,但这是不可取的。

因此,我找到了一些通过使用全局变量和覆盖全局元表赋值运算符来覆盖赋值运算符的独特解决方案,但我正在寻找是否有人可以帮助我阐述这个解决方案。参见 http://lua-users.org/lists/lua-l/2012-01/msg00413.htmlhttps://www.lua.org/pil/14.2.html . 特别是,我的变量是函数参数,而不是全局变量,所以我如何通过 C API 转换为全局变量,以便自定义 C 函数捕获任何赋值,如果赋值发生在全局用户数据上,该函数将采取行动?

顺便说一下,我的用户数据是一个指向对象的指针,以避免复制大对象,如果这很重要的话。

最佳答案

Lua和C/C++是不同的语言,有着不同的需求。在 C/C++ 中,变量总是引用一个特定对象。你可以改变这个对象的内容,但你永远不能让一个变量处理一个不同的对象。如果您执行 a = b;,则您将 b 的值复制到 a 中。您永远无法更改 a 正在谈论的对象。

在 Lua 中,变量不会永久引用任何东西。因此,变量当前持有的对象和该对象的值是有区别的。

您通过全局变量函数进行的拼凑,但是 local 变量实际上并不存在。它们是 Lua 栈上的位置;你不能覆盖 Lua 对它们的默认行为。

处理这个问题的最好方法是接受 C 和Lua 之间的区别。像在 Lua 中编写代码一样在 Lua 中编写代码。不要试图让 Lua 代码像 C 一样工作;那样做是愚蠢的。它们是不同的语言,您应该接受它们的差异,而不是反对它们。

如果你想让 Lua 有能力做与 a = b 等价的事情,那么你应该在你的类型中创建一个名为 assign 的函数或其他允许你分配给对象的值。就像如果您想将所有表格元素从一个表格复制到另一个表格一样,您必须编写一个函数来执行此操作。

关于c++ - 使用 C API 覆盖 Lua 中的赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38980090/

相关文章:

C++:获取 native dll依赖项而无需在进程中加载​​它

C++ 线程退出循环条件

c - 检测到堆栈粉碎且没有 getenv 的来源

lua - 返回表中最大或最小数的键

c++ - rand() 产生 1 个数字太高?

c - C 编程中的算术顺序

c - 递归中的段错误

object - 在 Lua 中制作和使用对象样式模块

Lua - 将带有参数的函数调用添加到堆栈并稍后调用它们

c++ - 如何修复 Werror=parentheses(建议在赋值周围使用括号)错误?