简体   繁体   中英

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). The userdata is passed in as arguments to event-like Lua functions that are called from my C++ program.

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.

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.

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. See http://lua-users.org/lists/lua-l/2012-01/msg00413.html and https://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?

By the way, my userdata is a pointer to an object to avoid duplicating large objects, if that matters.

Lua and C/C++ are different languages with different needs. In C/C++, a variable always references a specific object . 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; , you are copying the value of b into a . You can never change what object a is talking about.

In Lua, variables do not permanently reference anything. 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. They're locations on the Lua stack; you can't override Lua's default behavior with regard to them.

The best way to handle this is to accept the difference between C and Lua. Write code in Lua the way you would write code in Lua. Don't try to make Lua code work like 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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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