lua-users home
lua-l archive

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

On 19 August 2015 at 13:18, 云风 Cloud Wu <> 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.
> 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.
> 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.
> 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);

You're saying the slice offset would be stored in the userdata itself?
This would imply that setting a slice would mutate the userdata object?

If not, your slice still needs to create an extra object,
in which case, how is this better than the uservalue option?

void makeslice(lua_State *L, int idx, ssize_t offset) {
    idx = lua_absindex(L, idx);
    ssize_t* slice = lua_newuserdata(L, sizeof(ssize_t));
    *slice = offset;
    lua_pushvalue(L, idx);
    lua_setuservalue(L, -2);
void* getslice(lua_State *L, int idx) {
    ssize_t offset = *(ssize_t*)lua_touserdata(L, idx);
    void* udata = lua_touserdata(L, lua_getuservalue(L, idx));
    return udata+offset;

You would also need to add argument checking to the above.
But you *still* need to add metamethods to these objects.
e.g. You have a slice, but you need to define a getter/setters for the
struct components.
At which point, you might as well write a 'slice' customised for your
needs, as there won't be a general one-size-fits-all solution.

> 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.
> 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.

I'm not sure how this would work?
You need 64bits to store a userdata address on a 64 bit architecture.

> 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.

But you would still need a different object.