I think I saw somewhere a native function in Lua that can return a new userdata. Does it exist? Is it possible to create custom userdata from normal Lua script?
You may be thinking of newproxy
From: http://lua-users.org/wiki/HiddenFeatures
newproxy is an unsupported and undocumented function in the Lua base
library. From Lua code, the setmetatable function may only be used
on objects of table type. The newproxy function circumvents that
limitation by creating a zero-size userdata and setting either a new,
empty metatable on it or using the metatable of another newproxy
instance. We are then free to modify the metatable from Lua. This is
the only way to create a proxy object from Lua which honors certain
metamethods, such as __len.
It was also useful for __gc metamethods, as a hack to get a callback when the newproxy instance becomes free.
This feature was present in Lua 5.1, but removed in 5.2. In Lua 5.2, __gc metamethods can be set on zero sized tables, so the main impetus for newproxy went away.
Actually no, in pure Lua.
The type userdata is provided to allow arbitrary C data to be stored in Lua variables. … Userdata values cannot be created or modified in Lua, only through the C API. This guarantees the integrity of data owned by the host program.
link
If you embed luaVM in host C/C++ application, you can export some function to create userdata to Lua, but it's not a good practice. UD is designed to be a blackbox for Lua scripts.
Related
Hello everyone!
I've been studying metamethods and I realized something strange!
I already know all the metamethods presented in the Lua documentation as __add, __index, __newindex, etc... But I see around in forums and in questions around here people using metamethods like __ev , __close, __group, and I have never seen anywhere else these metamethods be used or exist in any documentation.
My question is, these metamethods exists? and if not, how are they created? and why people create this metamethods?
anyway, thanks for the attention
These are custom metamethods and have special purpose in specific project or framework.
Metamethods are used to extend functionality of table or userdata. These are most usable to achieve OOP behavior.
Some programmers add custom metatables and metamethods for internal purpose and better readability, such as __super, __extend, __inherit. In most cases such metadata are used from standard metamethods as __index, __call, ... or from routine methods to cleanup objects, error handling and so on.
For example __close could be used with connection or file objects to manage them in predictible way, __gc can't be trusted for this purpose.
Example of __group usage: Lua metatables and metamethod - How to call a different member function
In the lua programming language, I know that you can lock the metatable of userdata with the metamethod __metatable so that no-one can view the userdata's metatable with the getmetatable() function. But, I still want to access that metatable after its been locked. So, my question is, after the userdata's metatable is locked, is it still possible (maybe through some backdoor) to still get the metatable of the locked userdata, or is it just not possible (if so, then for what reasons)?
EDIT #1:
My motivation for wanting to know this is because I am trying to find a backdoor into Roblox's API so that I can more effectively script my games.
This applies at least to lua 5.3
In lua you can use the debug library method debug.getmetatable. That should return the original metatable regardless of the __metatable metamethod.
In C you can use the function lua_getmetatable for same purpose.
Also you could always make a variable somewhere to where you store the metatable and can access it later through that variable later.
Also if you used luaL_newmetatable, then you can still find the metatable in the registery with the metatable name you used.
You've stated you're using ROBLOX. When you think about it, they've locked this stuff for a reason. Why? Security purposes. Allowing scripters access to such things is dangerous and poses a serious threat. So the answer is no, once locked there is no way back into the metatable without a reference, because if there was the lock would be pointless.
ROBLOX also got rid of all functions in the debug library, but the recently added debug.traceback, so debug.getmetatable is definitely out of the question.
However, depending on your reasoning for this, there are others ways to accomplish the task. I'll go over some of them here:
1) If you want to set the metatable of an instance, make a fake instance using your own table, and then use __index and __newindex to control access to the object's properties and methods
2) If you want to set the metatable of a library, we follow the same approach as in 1, create a fake table and use __index to index the old table.
3) If you want to set the metatable of the global environment, set a new one with a pre-existing metatable. Make sure to use __index so the other variables still work!
As for simply reading the metatables, no you cannot do this.
In addition to that, if you lock your own tables, as mentioned earlier there is a way to access the metatable. Simply store a reference to it. The best way to do it would be make a local variable called meta in a do scope block.
I hope this answers your question, I tried to specifically target ROBLOX, since that's what your question was asking.
I want to pass a C++ object to Lua and use the same object in Lua. I have seen example of creating C++ objects in Lua and use them. But I want to do like this below.
Create a C++ object in C++ code
Pass this to Lua scripts and get some return values.
I have gone through these examples here.
http://loadcode.blogspot.sg/2007/02/wrapping-c-classes-in-lua.html
https://gist.github.com/kizzx2/1594905
But they are creating C++ objects in Lua and using them in Lua scripts.
can you please give some pointers.
Given that you did read some userdata manuals, it is very easy to achieve that. The only diference is that in regular ud manual they create objects in Lua function and you already have an object. Just push new userdata of pointer size and set it's metatable to Lua class's metatable (which you prepared anyway).
void **ud;
ud = lua_newuserdata(L, sizeof(*ud));
*ud = object; // existing
luaL_getmetatable(L, tname);
lua_setmetatable(L, -2);
// ud at top of stack
lua_setglobal(L, "foo");
Where tname is your Lua-side classes metatable name.
As you don't want to use the objects within Lua (just pass them on to C++), you can wrap them as a lightuserdata (see here) from C++, and later just pop it (you may want to check if it is_lightuserdata before).
SWIG considers C's enum as userdata. (I checked the source it generated. Perhaps a bug?). Then, I need to create userdata inside the Lua scripts itself... Any good ways?
Then, I need to create userdata inside the Lua scripts itself.
No. You want to create one of the enumerator values within Lua. You do that pretty much as you would in C: use the enumerator's name. This is an object that has the value of the enumerator. However SWIG's Lua component decides to marshal this is irrelevant; just use the name in your Lua code.
When making Lua bindings for C++ classes, should I return tables or userdata objects?
Does anyone know any of the pros and cons for each method?
I recommend returning userdata. Regardless of approach, there has to be somewhere to put the pointer
to the C++ data, or the actual C++ data itself, and there's nowhere
safe to do this with a table.
Returning tables would make sense in some situations, because they can
be 'annotated' in Lua with extra attributes without one's having to do
anything extra to support this. Unfortunately the C++ object pointer
has to go somewhere, and there's nowhere sensible for it to go other
than an actual entry in the table itself.
This is not a very safe place for it to go. It can be found by Lua
code, and removed or replaced. This could be by accident, or on
purpose, it doesn't really matter.
My preference therefore is to return userdata objects. They can be
made to work like tables if one really must insist upon that, but they
also have a "secret" area (the actual userdata itself) where the C++
object pointer can be stored, safe from overwriting by Lua code.
(Userdata objects also have an "environment" pointer, which is another
place to store object-specific data. As with the userdata payload
itself, this value is inaccessible to Lua code and can't be damaged
that way.)