[英]Override Assignment Operator in Lua with C API
我在我的C ++程序中有对象,我将其作为userdata传递给Lua,并且我覆盖此userdata的metatable,以便对象的索引(通过__newindex和__index)的赋值导致对C的调用,这将转换赋值影响C ++对象或将C ++元素转换为Lua值(另一个用户数据或基本类型,如bool,number,string)。 userdata作为参数传递给从我的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布尔值分配给我的内部C ++对象,但是如果我这样做: lua_userdata_object_passed_as_arg_to_event = new_object()
它将改变Lua变量引用的内容,但是根据我的理解,它不会对核心对象做任何事情。
我考虑过的一个解决方法是,如果他们想要更改对象本身,则需要开发人员执行lua_userdata_object_passed_as_arg_to_event["__self"] = new_object()
。但这是不可取的。
所以我找到了一些独特的解决方案,通过使用全局变量和覆盖全局metatable赋值运算符来覆盖赋值运算符,但我希望看看是否有人可以帮我解释这个解决方案。 请参阅http://lua-users.org/lists/lua-l/2012-01/msg00413.html和https://www.lua.org/pil/14.2.html 。 特别是,我的变量是函数参数,而不是全局变量,所以我如何通过C API转换为全局变量,以便任何分配将被自定义C函数捕获,如果分配发生在全局用户数据上,它将采取行动?
顺便说一下,我的userdata是一个指向对象的指针,以避免重复大对象,如果这很重要的话。
Lua和C / C ++是具有不同需求的不同语言。 在C / C ++中,变量始终引用特定对象 。 您可以更改此对象的内容,但永远不能使变量处理不同的对象。 如果你做a = b;
,你正在将b
的值复制到a
。 你永远无法改变什么对象a
都在谈论。
在Lua中,变量不会永久引用任何内容。 因此,当前变量所持有的对象与该对象的值之间存在区别。
你的kludge通过全局变量函数,但local
变量是不存在的东西。 它们是Lua堆栈上的位置; 你无法覆盖Lua关于它们的默认行为。
处理这个问题的最好方法是接受 C和Lua之间的区别。 在Lua中编写代码就像在Lua中编写代码一样。 不要试图使Lua代码像C一样工作; 那种方式很愚蠢。 它们是不同的语言,你应该接受它们的差异,而不是反对它们。
如果你想让Lua能够执行相当于a = b
,那么你应该在你的类型中创建一个名为assign
的函数或者允许你分配给对象值的函数。 就像您想要将所有表元素从一个表复制到另一个表一样,您必须编写一个函数来执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.