Object binding comments wanted

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Object binding comments wanted

David Given
I wish to implement a binding system for my OS's object model.

The way I want this to work is to have a mechanism whereby I can wrap an 
arbitrary native object to turn it into a Lua object. I can inspect the 
native object to determine which interfaces it supports, and then generate 
the bindings for its methods on-the fly.

The problem is figuring out how to do this efficiently. The naive way of doing 
it is rather inefficient. If I have a native object that implements 
interfaces A, B and C, each of which have 50 methods each, then importing 
that object will generate a Lua table containing 150 entries. Importing 
another object that implements interfaces B and C will cause a second table 
to be generated containing 100 entries. While I can share the function 
objects in the tables themselves, I'm still going to end up with big, bloaty 
Lua tables representing my objects.

An alternative system is to have a seperate table that represents each 
interface, and have the __index metatable entry for the object itself look up 
each interface in turn. This would be nicely memory-efficient, because all 
the object table needs to store is the list of supported interfaces, but will 
require dropping into Lua code to look up every method call on the object, 
which will be slow. (Rewriting the dispatcher in C would help but I'm still 
not terribly happy.)

Can anyone suggest any other approaches I could look at?

-- 
+- David Given --McQ-+ "...it's not that well-designed GUI's are rare,
|  [hidden email]    | it's just that the three-armed users GUI's are
| ([hidden email]) | designed for are rare." --- Mike Uhl on a.f.c
+- www.cowlark.com --+ 

Attachment: pgpyZvEimAwV5.pgp
Description: PGP signature

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Adam D. Moss
Hi!

David Given wrote:
An alternative system is to have a seperate table that represents each interface, and have the __index metatable entry for the object itself look up each interface in turn. This would be nicely memory-efficient, because all the object table needs to store is the list of supported interfaces, but will require dropping into Lua code to look up every method call on the object, which will be slow. (Rewriting the dispatcher in C would help but I'm still not terribly happy.)

I don't really know what you mean about dropping into Lua to look up
every method call.  I don't imagine that every combination of interfaces
is actually used by objects - make a table which is shared by each
'class', which is what you really have there, not one big table shared
by every class which is then filtered per-object.  Then no dispatcher.
This would be the usual way people implement classes in Lua.

Can anyone suggest any other approaches I could look at?

As well as a more straightforward approach such as above, I do
also recommend trying-before-optimizing.  Lots of details which
it's easy to assume will be too slow, just get lost in the noise
in real benchmarking.  That said, method invokation is an important
case, but without the dispatcher madness it's just a metatable
lookup and a function call.  Note that if a __index value is a
table instead of a function, Lua will handle a lookup into that
table itself instead of you having to write any sort of trivial
dispatcher for that case.

cheers,
--adam
--
Adam D. Moss   -   [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

David Given
On Friday 23 September 2005 12:35, Adam D. Moss wrote:
[...]
> I don't really know what you mean about dropping into Lua to look up
> every method call.  I don't imagine that every combination of interfaces
> is actually used by objects - make a table which is shared by each
> 'class', which is what you really have there, not one big table shared
> by every class which is then filtered per-object.

Well, the actual class isn't important --- it's the interfaces implemented by 
the class that's important. Think Java; we have an object that implements 
Vector and Synchronisable, therefore we need to generate bindings for those 
particular methods, while the fact that this is actually an instance of 
my.dodgy.app.Fnord is irrelevant. (Actually, our objects are probably going 
to implement about four interfaces each.)

But I see what you mean. If I generate a seperate dispatch table for each 
*combination* of interfaces, then I should get reasonable speed *and* memory 
efficiency (because the number of objects in use should vastly outweigh the 
number of dispatch tables). Hmm...

-- 
+- David Given --McQ-+ "If you're up against someone more intelligent
|  [hidden email]    | than you are, do something insane and let him think
| ([hidden email]) | himself to death." --- Pyanfar Chanur
+- www.cowlark.com --+ 

Attachment: pgptWEARwHk9c.pgp
Description: PGP signature

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Shannon Stewman
In reply to this post by David Given
On Fri, Sep 23, 2005 at 11:26:03AM +0100, David Given wrote:

> An alternative system is to have a seperate table that represents each 
> interface, and have the __index metatable entry for the object itself look up 
> each interface in turn. This would be nicely memory-efficient, because all 
> the object table needs to store is the list of supported interfaces, but will 
> require dropping into Lua code to look up every method call on the object, 
> which will be slow. (Rewriting the dispatcher in C would help but I'm still 
> not terribly happy.)

I use this for my binding to Gtk's GObject system and haven't found the
results of a C dispatcher to be slow.  Behind the scenes, maintain a
table for each class/interface and have the dispatcher look through the
tables in its search through the class hierarchy.  This avoids dealing
with non-interned strings, so all your potentially costly string
operations are handled with hashing.

Best,

-- 
Shannon Stewman         | Let us walk through the waning night,
Caught in a whirlpool,  | As dawn-rays tickle our toes, the dew soothes
A quartering act:       | Our blistered soles, and damp bones stir
Solitude or society?    | As crimson cracks under the blue-grey sky.

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Eric Jacobs
In reply to this post by David Given
On Fri, 23 Sep 2005 15:04:37 +0100
David Given <[hidden email]> wrote:

> 
> Well, the actual class isn't important --- it's the interfaces implemented by 
> the class that's important. Think Java; we have an object that implements 
> Vector and Synchronisable, therefore we need to generate bindings for those 
> particular methods, while the fact that this is actually an instance of 
> my.dodgy.app.Fnord is irrelevant. (Actually, our objects are probably going 
> to implement about four interfaces each.)

I have a situation similar to this. I've grown fond of the following technique
to call object methods. I think it's a big win once you get used to its
syntax:

        obj[intf.method]()

Here, the intf.method can be a userdata that points directly at your
underlying object system's method descriptor structure. When the __index
metamethod gets the userdata, all it has to do is prepare the arguments
and then do the method dispatch just as a call in your native implementation
would do. You don't have to do a string lookup at call-time (although this
isn't terrible in Lua because strings are automatically interned), plus
you have full immunity to namespace collision problems among interfaces.

Eric

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Eric Jacobs
In reply to this post by David Given
On Fri, 23 Sep 2005 15:04:37 +0100
David Given <[hidden email]> wrote:

> 
> Well, the actual class isn't important --- it's the interfaces implemented by 
> the class that's important. Think Java; we have an object that implements 
> Vector and Synchronisable, therefore we need to generate bindings for those 
> particular methods, while the fact that this is actually an instance of 
> my.dodgy.app.Fnord is irrelevant. (Actually, our objects are probably going 
> to implement about four interfaces each.)

I have a situation similar to this. I've grown fond of the following technique
to call object methods. I think it's a big win once you get used to its
syntax:

        obj[intf.method]()

Here, the intf.method can be a userdata that points directly at your
underlying object system's method descriptor structure. When the __index
metamethod gets the userdata, all it has to do is prepare the arguments
and then do the method dispatch just as a call in your native implementation
would do. You don't have to do a string lookup at call-time (although this
isn't terrible in Lua because strings are automatically interned), plus
you have full immunity to namespace collision problems among interfaces.

Eric

Reply | Threaded
Open this post in threaded view
|

Object binding (Gtk)

Wolfgang Oertl-2
In reply to this post by David Given
Hi,

I read "binding to Gtk's GObject" and thought, I've done that
before.  You might want to look at the lua-gtk2 library which
is available on luaforge.net.

It uses automatically generated information about function
parameters; the whole library is about 130k for access to about
4600 functions, 400 structures and 1400 enums.  This is in
contrast to the usual bindings where one stub function is created
per library function leading to several MB of code.

Multiple inheritance (or "interfaces") are supported, too.

Unfortunately this does not make Gtk-2 smaller than it is, so the
net result is still a somewhat large memory footprint.

Cheers,
Wolfgang Oertl


Reply | Threaded
Open this post in threaded view
|

Re: Object binding (Gtk)

Asko Kauppi

hmm.. one thing to note (sorry, haven't followed the discussion..) is that the GLib side should hardly be ported to Lua. Those things are simply platster stickers trying to make C behave like a language it is not. Lua has such stuff built in. :)

-ak

Wolfgang Oertl kirjoitti 24.9.2005 kello 21.38:

Hi,

I read "binding to Gtk's GObject" and thought, I've done that
before.  You might want to look at the lua-gtk2 library which
is available on luaforge.net.

It uses automatically generated information about function
parameters; the whole library is about 130k for access to about
4600 functions, 400 structures and 1400 enums.  This is in
contrast to the usual bindings where one stub function is created
per library function leading to several MB of code.

Multiple inheritance (or "interfaces") are supported, too.

Unfortunately this does not make Gtk-2 smaller than it is, so the
net result is still a somewhat large memory footprint.

Cheers,
Wolfgang Oertl




Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Mark Hamburg-4
In reply to this post by Eric Jacobs
on 9/23/05 5:17 PM, Eric Jacobs at [hidden email] wrote:

> I have a situation similar to this. I've grown fond of the following technique
> to call object methods. I think it's a big win once you get used to its
> syntax:
> 
>       obj[intf.method]()
> 
> Here, the intf.method can be a userdata that points directly at your
> underlying object system's method descriptor structure. When the __index
> metamethod gets the userdata, all it has to do is prepare the arguments
> and then do the method dispatch just as a call in your native implementation
> would do. You don't have to do a string lookup at call-time (although this
> isn't terrible in Lua because strings are automatically interned), plus
> you have full immunity to namespace collision problems among interfaces.

Does this rely on the __index metamethod generating a custom closure for
each call (possibly cached) to make the value of obj available?

I actually rather like this as a way to avoid namespace collisions on
methods, but it perhaps needs syntactic support in the form of something
like:

    obj:[intf.method]()

Mark


Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

David Given
In reply to this post by Eric Jacobs
On Saturday 24 September 2005 01:05, Eric Jacobs wrote:
[...]
> I have a situation similar to this. I've grown fond of the following
> technique to call object methods. I think it's a big win once you get used
> to its syntax:
>
>         obj[intf.method]()

I quite like this --- it's elegant. Unfortunately, I doubt my users will 
agree... I suspect they'd prefer traditional syntax.

I think what I'll do is to have a table that represents each interface, 
containing bindings for the methods, created lazily, and then have a C 
dispatcher on the object that tries each interface in turn. I think in this 
case the reduced complexity outweighs the performance improvements in trying 
to do anything more complex; plus, with appropriate metatable abuse I can do 
the hard work in generating the bindings from Lua, which would be nice.

Thanks, everyone!

-- 
+- David Given --McQ-+ "The first 90% of the code takes the first 90% of
|  [hidden email]    | the time. The other 10% takes the other 90% of the
| ([hidden email]) | time." --- Anonymous
+- www.cowlark.com --+ 

Attachment: pgpUI6XCxSRlP.pgp
Description: PGP signature

Reply | Threaded
Open this post in threaded view
|

Re: Object binding comments wanted

Mark Hamburg-4
Another option is:

    intf.method( obj )

In other words, treat the methods more like generic functions. Each of the
methods in the intf table could be the same piece of C code with a different
up value indicating what to dispatch to. For example, writing in Lua:

    function dispatch( obj, ... )
        local method_imp = obj[ method_id ] -- method_id is an up value
        assert( method_imp )
        return method_imp( obj, ... )
    end

Mark

on 9/26/05 5:51 AM, David Given at [hidden email] wrote:

> On Saturday 24 September 2005 01:05, Eric Jacobs wrote:
> [...]
>> I have a situation similar to this. I've grown fond of the following
>> technique to call object methods. I think it's a big win once you get used
>> to its syntax:
>> 
>>         obj[intf.method]()
> 
> I quite like this --- it's elegant. Unfortunately, I doubt my users will
> agree... I suspect they'd prefer traditional syntax.
> 
> I think what I'll do is to have a table that represents each interface,
> containing bindings for the methods, created lazily, and then have a C
> dispatcher on the object that tries each interface in turn. I think in this
> case the reduced complexity outweighs the performance improvements in trying
> to do anything more complex; plus, with appropriate metatable abuse I can do
> the hard work in generating the bindings from Lua, which would be nice.
> 
> Thanks, everyone!