lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I'm trying to follow along as I lurk. I have questions[1]:


On Tue, Aug 18, 2015 at 10:18 PM, 云风 Cloud Wu <cloudwu@gmail.com> wrote:
> Lua is a embedded language, it uses powerful userdata to wrap the c object
> as the lua object. But sometimes it's not enough.
>
> For example, if we have a C struct like this :
>
> struct foo {
>   struct foo1 foo1;
>   struct foo2 *foo2;
> };
>
> We can use userdata to store struct foo in lua variables :
>
> struct foo * f = lua_newuserdata(L, sizeof(*f));
>
> How to reference sub struct foo1/foo2 in lua ? maybe we can give the
> userdata a metatable, implementing an __index metamethod.

You have a userdata object inside of Lua. You need to provide access
to fields within that object. The object in this example has one(?)
level, but your point is that there may be many. For example, you may
be representing a tree structure.

As the Lua program indexes into the userdata, there is a need to do
book keeping. This...

```
foo = mylib.new_ud()
local foo_foo1 = ud.foo1
local foo1_baz = foo_foo1.baz
```
...is harder than it looks because you need to do book keeping on the
fields, so that you know that foo belongs to a specific `foo` object.
You can't collect `foo` until `foo_foo1` has been collected. Similar
concerns exist with finding `foo_foo1.baz`

>
> But foo.foo1 or foo.foo2 should be a new userdata. It needs more complex and
> expensive way :
>
> Creating a proxy userdata to access a part of struct foo, put the reference
> of proxy userdata in uservalue of userdata foo to prevent collecting foo
> before foo1/foo2 proxy, etc.

Here you are saying that the existing situation requires something like:
```
local foo_foo1 = foo.foo1 -- the __index method of ud finds `foo1`,
makes a new ud for it and then you store that reference in the
userdata of foo
```


After this, you lost me...
>
> So I suggest introduce a new mechanism of userdata to simplify them. I call
> it userdata slice (maybe it's not a good name).
>
> If we can associate an integer to the userdata value, the userdata whould be
> more flexible. It is different from uservalue, because uservalue is in
> userdata object, not in value.

I think that you are saying that this integer would be in the C
struct, not in the Lua-created userdata wrapper around the C struct?

But then what you say next doesn't support that understanding...

>
> An userdata object has only one uservalue , but each userdata value can has
> an unique associated integer.
>
> Two C API needed:
>
> int lua_getuserslice(lua_State *L, int index);
> void lua_setuserslice(lua_State *L, int index, int slice);
>
> Any value with type LUA_TUSERDATA in lua is an two 32bit integer tuple ( or
> two 16bit integer for small lua), one is the userdata (32bit int) handle ,
> another is the associated integer.
>

Did you just re-introduce near and far pointers? :)


> Using handle instead of really address of userdata object because we can put
> two 32bit integer in 64bit lua value.
>
> I think it's easy to implement and keep the c api compatibility with the
> previous version.
>
> Storing C/C++ objects in GUI or 3d engines could be more simple : OBJECT.X
> and OBJECT.X.Y can be the same userdata with OBJECT without creating new
> userdata, only the slice is different.
>


I think that what you are saying is that the value you would get back
would be a new userdata slice that had the same handle/pointer in the
first part of the tuple, but a unique integer (offset) in the second.

Conceptually, I think that your suggestion boils down to:

A mechanism to efficiently and safely traverse a C structure inside of
Lua, without needing to manually create the necessary book keeping
code that is required to handle garbage collection and also "which
object does this field belong to?"

The intent of your proposal is to have lua make the "proxy" ud objects
and for the api to provide a nice way to clean them all up, or to stop
them from being cleaned up, if references to fields within the root-ud
object are still present. The justification is that this is a common
use case. Presumably, you also believe that the various mechanisms
that are currently around to do this are tedious and not necessary?

You seem to imply that Lua's userdata structures are large enough that
the concept of a slice would make things better. How much smaller
would a slice be? Is there some other advantage to a slice?


[1] In part, my questions are asked to help with my general CSCI
understanding, so some of them may seem odd. Roberto said, "yes we all
know how to program..."... Well, that's only true to a degree. :)