2

I can obtain a userdata from inside my C++ code. I want to know if I can cast it to something so I can dereference its fields and invoke its methods without going through Lua.

In other words:

Once I obtain an userdata and put it in the Lua stack, how can I get it out and use it as an object of a certain class? I know all fields and methods that I'm interested in (their Lua names), but not necessarily all fields and method the userdata underlying implementation provides.

Is there a way to somehow create an interface that would know the offsets of each member?

I believe the question is, how do I know the offset of each member in the Lua view of the userdata, so I can create a struct to cast the void * returned by lua_touserdata to?

FinnTheHuman
  • 1,115
  • 13
  • 29

1 Answers1

1

Userdata is just a binary blob. Array of bytes. How those bytes will be interpreted - depends entirely on interface provided with that userdata, be it metatable with methods, or some other agreements.

If that userdata created by your code, then you either know what type of native object is there (knowing that some func generate or accept only specific type), or you can place type identifier as first bytes of userdata blob, so you can check that id and switch/cast userdata pointer to a specific class.

If that userdata created by someone's code - you can only rely on methods provided within its metatable (you can access it from native code), or just treat is as array of bytes, without possibly knowing actual type of data stored there. Or do some hackish guesses, making it working in some cases, and crashing badly if your guess wasn't correct.

Vlad
  • 5,450
  • 1
  • 12
  • 19
  • There's no way of "asking Lua" the offset of a given member? – FinnTheHuman Apr 29 '17 at 10:30
  • 2
    @FinnTheHuman: The members of a userdata don't necessarily correspond to any 'real' C (sub-)object; they are just syntactic sugar for calls to the `__index` or `__newindex` metamethods. Since these metamethods can do anything, and are not limited to just returning a fixed reference to a part of the blob, Lua can't possibly give an offset for a given member. If you just want to do the equivalent of calling these metamethods, but from C rather than from Lua, just use `lua_getfield` or `lua_setfield` (which will trigger any metamethods if they are present). – Mankarse Apr 29 '17 at 10:34
  • @Mankarse Thank you. So the only way to skip Lua would be to get the type author to create an actual interface for it? – FinnTheHuman Apr 29 '17 at 10:37
  • 2
    @FinnTheHuman: Yes. You would need to have the author supply an functions which operate on an opaque pointer to the userdata type, or you would need the author provide struct declarations that present a guaranteed interface; which you could cast the userdata to. – Mankarse Apr 29 '17 at 10:40