Suggestion - userdata
boq opened this issue ยท 7 comments
Note: I'm starting this discussion to check, if it would be accepted, before I start implementing it - so it's not exactly suggestion, but RFC
Userdata in pure Lua is data opaque for language, but accessible by C code. I think such concept would still be useful in CC - addons would be able to return custom data and transparently pass it through interpreter. For example, it would be useful for wrapping ItemStack - peripherals may want to operate directly on in (instead of some serialization to native Lua types). This proposal is composed of two parts:
IUserdata
interface
This marker interface (no methods) causes type converter to pass values unchanged (both directions). While in Lua domain, values can still have metatable attached (via org.luaj.vm2.LuaUserdata
type).
'Native' libs
To make anything useful with userdata user must have access to native
methods provided by peripheral. New method would be added to IComputerAccess
:
public void mountLib(String id, ILuaObject object);
Method would add new library either to global scope or to something like lib.[id]
. Inside that library would be methods used to operate on userdata (so for example, in ItemStack scenario, wrapper that sets metatable and various methods used in there, like getSize()
, etc).
Does the native access really need to happen? It should work perfectly fine without, no?
Alternative would be adding method like getItemStackMetamethods
to peripheral. Sure, it's doable, but it's only weakly related to peripheral and more to type itself. Also, access to lib-like almost-global object would be easier for user.
Hmm. I am kinda unsure of usefulness of this whole thing to the user. If i am getting it right this would allow to pass data from one peripheral to other right?
That's basic idea. But I also want to be able to add _index
in metatable (or other metamethods), so it is possible to return values that are similar to native ones.
As a addon author, there are certain things that I want to hide from user (or serialization would be impractical), but still be able to use in addon. Native access is just way to control what interface user sees.
A userdata object could simply have the same getMethodNames
and callMethod
that an IPeripheral
has. Returning such an object would give the Lua side a userdata object with methods on it, passing that back into a peripheral function would then pass the very same object as one of the arguments, and could be checked using instanceof MyUserdata
... I don't see any problem there.
Well, we already have ILuaObject
, why don't we use that?
Since during conversion it's unpacked into LuaTable with LuaFunctions - initial identity of object is hidden behind two layers of Lua objects.
Maybe we can rework ILuaObject
to use metafunction _index
instead and unpeel it at call to peripheral? That's one solution, but switching from table to singular function may cause slight side-effects.
Cloning ILuaObject
interface to IUserdataObject
? Duplication is never good.
Anyway I think native library idea has use outside of userdata support (for example, to provide general use library?). It can also provide constructors for userdata, while ILuaObject
approach can at most provide prototype/clone
functionality.