简体   繁体   English

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

[英]Override Assignment Operator in Lua with C API

I have objects in my C++ program that I pass to Lua as userdata, and I override the metatable for this userdata so that assignments to and from indices of the object (via __newindex and __index) result in a call to C, which converts the assignment to affect the C++ object or convert the C++ element to a Lua value (either another userdata or a base type like bool, number, string). 我在我的C ++程序中有对象,我将其作为userdata传递给Lua,并且我覆盖此userdata的metatable,以便对象的索引(通过__newindex和__index)的赋值导致对C的调用,这将转换赋值影响C ++对象或将C ++元素转换为Lua值(另一个用户数据或基本类型,如bool,number,string)。 The userdata is passed in as arguments to event-like Lua functions that are called from my C++ program. 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 */

However, this doesn't allow me to assign the actual variable itself, only an index of the variable. 但是,这不允许我自己分配实际变量,只允许变量的索引。 There is no meta-event for directly overriding the assignment operator, so I am looking for a workaround. 没有用于直接覆盖赋值运算符的元事件,因此我正在寻找一种解决方法。

In other words, I can do this: lua_userdata_object_passed_as_arg_to_event["is_it_true"]=true and it assigns the Lua boolean to my internal C++ object, but if I do this: lua_userdata_object_passed_as_arg_to_event = new_object() it will change what the Lua variable references, but it won't do anything to the core object as I understand it. 换句话说,我可以这样做: 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变量引用的内容,但是根据我的理解,它不会对核心对象做任何事情。

One workaround I've considered is some hack requiring developers to do lua_userdata_object_passed_as_arg_to_event["__self"] = new_object() if they want to change the object itself, but this is undesirable. 我考虑过的一个解决方法是,如果他们想要更改对象本身,则需要开发人员执行lua_userdata_object_passed_as_arg_to_event["__self"] = new_object() 。但这是不可取的。

So I've found some unique solutions to overriding the assignment operator by using global variables and overriding the global metatable assignment operators, but I am looking to see if anyone can help me expound this solution. 所以我找到了一些独特的解决方案,通过使用全局变量和覆盖全局metatable赋值运算符来覆盖赋值运算符,但我希望看看是否有人可以帮我解释这个解决方案。 See http://lua-users.org/lists/lua-l/2012-01/msg00413.html and https://www.lua.org/pil/14.2.html . 请参阅http://lua-users.org/lists/lua-l/2012-01/msg00413.htmlhttps://www.lua.org/pil/14.2.html In particular, my variables are function arguments, not globals, so how can I convert to globals through the C API so that any assignments will be captured by a custom C function that will take action if the assignment is happening to a global userdata? 特别是,我的变量是函数参数,而不是全局变量,所以我如何通过C API转换为全局变量,以便任何分配将被自定义C函数捕获,如果分配发生在全局用户数据上,它将采取行动?

By the way, my userdata is a pointer to an object to avoid duplicating large objects, if that matters. 顺便说一下,我的userdata是一个指向对象的指针,以避免重复大对象,如果这很重要的话。

Lua and C/C++ are different languages with different needs. Lua和C / C ++是具有不同需求的不同语言。 In C/C++, a variable always references a specific object . 在C / C ++中,变量始终引用特定对象 You can change the contents of this object, but you can never make a variable deal with a different object. 您可以更改此对象的内容,但永远不能使变量处理不同的对象。 If you do a = b; 如果你做a = b; , you are copying the value of b into a . ,你正在将b的值复制到a You can never change what object a is talking about. 你永远无法改变什么对象a都在谈论。

In Lua, variables do not permanently reference anything. 在Lua中,变量不会永久引用任何内容。 Thus, there is a distinction between the object the variable currently holds and the value of that object. 因此,当前变量所持有的对象与该对象的值之间存在区别。

Your kludge via global variables functions, but local variables are things that don't really exist. 你的kludge通过全局变量函数,但local变量是不存在的东西。 They're locations on the Lua stack; 它们是Lua堆栈上的位置; you can't override Lua's default behavior with regard to them. 你无法覆盖Lua关于它们的默认行为。

The best way to handle this is to accept the difference between C and Lua. 处理这个问题的最好方法是接受 C和Lua之间的区别。 Write code in Lua the way you would write code in Lua. 在Lua中编写代码就像在Lua中编写代码一样。 Don't try to make Lua code work like C; 不要试图使Lua代码像C一样工作; that way is folly. 那种方式很愚蠢。 They are different languages, and you should embrace their differences, not work against them. 它们是不同的语言,你应该接受它们的差异,而不是反对它们。

If you want to give Lua the ability to do the equivalent of a = b , then you should create a function in your type called assign or something that will allow you to assign to the object's value. 如果你想让Lua能够执行相当于a = b ,那么你应该在你的类型中创建一个名为assign的函数或者允许你分配给对象值的函数。 Just like if you want to copy all of the table elements from one table to another, you have to write a function to do that. 就像您想要将所有表元素从一个表复制到另一个表一样,您必须编写一个函数来执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM