lua-users home
lua-l archive

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




On Tuesday, September 16, 2014, Udo Schroeter <udo.schroeter@gmail.com> wrote:
Hey Dirk,

I'm relatively new to Lua, so take this with a grain of salt.

I would advise against returning a normal table. There would be no way to protect internal fields if you store them there, but more importantly keeping the connection between the Lua table and your window object itself alive could potentially be a major hassle.

Instead, have a look at the liolib.c as an example. There, they use a userdata base object for each file, and associated with it is the standard metatable for files. However, in your case, you would associate your window userdata object with a brand new table when it's constructed. The user can then modify that metatable to set event handlers or other data.

This has the added advantage that you can always easily retrieve the user-defined event handler for any given action from the C side by accessing the metatable.




On Tue, Sep 16, 2014 at 9:54 AM, Dirk Schippers <lua@frixx-it.com> wrote:
Hi,

I am creating a test project (C++) where I have this telnet server which creates a thread for every connected client that has its own Lua environment to play around in.
But I want to do more than: print 5 + 2
So I created some functions: createWindow({...}) which creates a window. I can call it multiple times to create multiple windows.

At this time, the function has become the constructor for an object, which returns a light userdata pointing to a C-struct containing the window handle and some other stuff.

But I want to expand this: I want the return value to become a table where you can put your own events handlers in, like this:

w = window.new({...})
w._onMouseMove_ = function(x, y)
    ...
end

I would also like to be able to pass the event function immediately to the constructor as well but still keep the ability to update the event later on.

Now the question is, how do I handle this: do I create a table (instead of a light userdata) in the constructor for window and add a metatable to it? How should I handle the optional event declaration? Do I need to override the __index or should I keep all of it in lua? How can I call the correct event function in the correct object when I receive the events in my message loop? If I use tables, I don't know how to find them back... How can I keep an index between the window handle and a lua table?
Where do I put the window-handle and stuff like that, whilst keeping the table safe so that noone can change this window handle through Lua code and corrupt the environment? Do I put an extra light userdata inside the table? Can I protect that one?

I know this is a big question but I have the feeling that the answer will be simpler.

Dirk.



I have the same caveat, as well, but offer my understanding, mostly for fun. 

I believe thet this is exactly what lightuserdata is for: identity. The window handle is used to create your lightuserdata object. When the callback fires, this window handle will match your lightuserdata, which can be used as an index in a lookup table that is stored in the registry.

In 5.3, I believe that this lightuserdata can also be used directly as a uservalue, if you'd like your object to be stored as userdata. The lightuserdata is used for identity and perhaps other C-side structures might be stored in the full userdata?  However, I don't believe thst this is required for safety. If your worried about someone messing with it, you could use the `__metatable` field, but since you can't change the value of lightuserdata, it's hard to see the damage caused that is beyond the scope of Lua.

Anyway, I used this technique in my yet-to-be-finished NanoMsg binding. I'm 0-10+ in helpful advice, so I'll be interested in other answers. 

-Andrew