Re: New 'GObject' as base for GtkObject?



> On Fri, 10 Dec 1999, Karl Nelson wrote:
> 
> > > On Thu, 9 Dec 1999, Karl Nelson wrote:
> 
> > The short point he was trying to make is that
> > an object system is good, but it does not completely get you to the
> > same point that a language enforcing those constraints would give.
> > Thus people either from inexperience or "clever" use of they system
> > will create new and unbindable patterns.  This inconsistancy 
> > can completely defeat even the most elegant plans for wrapping.
> 
> ok, i now understand that with "consistency" you mean consistent use
> of the object system for varous kinds of structures.
> there are certainly places in gtk/gdk where it we should use some
> GObject-alike base type and greatly aid language bindings with that,
> that's especially the case with some Gdk structures.

> but as owen already pointed out, the GtkObject system doesn't allow
> for such fine grained object hirarchies as you would use them on C++
> it doesn't make a whole lot of sense to make GList derive from some
> object base structure for instance.

Agreed.  My problem with GList is not that it doesn't derive
from the object, but rather that you can't make something 
that works like it but isn't.  Ie.  I have a C++ list that I
want gtk+ to use.  My current solution is to build a GList 
just for that interface, call it, then destroy the list.  This
is the same with the gqueue.  I can't just go in and 
take out something glist and make a gqueue because glist
methods don't work on gqueue.  There is a level of abstraction
missing.  (implementation is transparent.)  Fortunately,
I know I can't convince him so I will go pick another battle. 
   
> Gtk+ is not only a toolkit created for language bindings, but also
> to be usable in C, so you will come around structures that are there
> for convenient use in C programs and not to create bindings from,
> rather the bindings need to implement their own language-specific
> interfaces sometimes and wrap that onto the C interface.

Most of the places I am talking about making the interface 
which deals with the specifics and then a user level wrapper
wouldn't be much of a pain.  It is just that our current
approach is to duplicate the gtk+ code that does too much
into our source and then have to maintain it there. Yuck!

> i don't know how you handle GtkItemFactoryEntry in C++, but i
> defintely don't see a point in having that be implemented as an object,
> the whole point about this structure is to be able to layout C arrays
> in a compact way and create whole menu hirarchies from that.
> you could adapt that for C++ with a wrapper structure Gtk_ItemFactoryEntry
> if you wanted to and/or cookup your own interface e.g. like
> factory.create_item ("path", "accelerator", function, "type");
> C++ is actually the one language that should have the least headaches
> with the provided C interfaces.

Itemfactory was an unholy mess for us.  We tried to a year
(from time to time) poking at making a wrapper for it.
We had to rewrite all of Item factory into C++.  The interface
was a bolt on to the gtk+ kit and should have been at in 
menu_shell to begin with.  A lot of these structures are added
later like tooltips which would work a lot better (in OO) had
they just been added as new features to the original kit.)

> > > so if you'd shortly outline what consistancy you are talking about
> > > and provide a pointer to that gtkprocess header generator you are
> > > talking about, i'd apprechiate that.
> > 
> > Sure not a problem.  Consistancy would be to have the elements that
> > are related always be related in the same way.  For example if I
> > have a public signal exposed to the user it should have
> >  
> >   - the same name for its emit function and signal name should
> >     always have the same relationship.  (Not like gtk+ functions
> >     that have boo-bar and gtk_foo_boo_bar)
> 
> wait, one convention in gtk is actually to name emit functions (the
> functions that emits the signal) after their signal name (or vice versa),
> so if you have a ::boo_bar signal for a GtkFoo object, the function
> should be named gtk_foo_boo_bar () and the class method (the vfunc called
> upon the signal emission) should also be named boo_bar().
> so what are you referring to here?

The some signals where that was not true...
 "set-editable", "add-accelerator", "remove-accelerator", 
 "set-focus-child", "selection-done"

(I think we get away with these just because the signal
system cuts out _ and -, but still it breaks code generators
and confuses the conventions.)

> >   - the same meaning for the emit function and signal name.
> >     (Some emit functions in gtk+ do different things when called
> >     through a function and called directly.)
>
> (i assume with emit function you mean the class vfunc here), class
> methods that are called from signal emissions are part of the signals
> implementation and shall never be called directly but only during
> their signal's emission.

No, by emit function I mean the function the user calls to
start the signal.  Vfunc is the optional cheap slot in the signal.
Unfortunately, some gtk+ widgets add their own spin to the
emit function so the function of the user calls and the signal
don't match.  

(basically they wanted the system I described later in my message
where a function calls the signal so they add something to the
emit function that directly changes the widget and then progress
the signal which still may go to yet another handler.)
  
> >   - the same arguments shared between signal and emit functions,
> >     and the virtual function.
> 
> can you give a concrete example here? the signal emitting function
> and the vfunc should normally have the same arguments (and the
> signal must have the same arguments as the vfunc, otherwise
> marshalling simply doesn't work).

Several signals "emit" functions add arguments to signals that
correspond.   Ie.  Druid page has a function gnome_duid_page_next
that adds an extra argument.  The extra argument is the parent,
which is easily found from the object itself.  Since signals and
functions share the same namespace in C++, this is bad for us. 

> >   - signals are either private or public.  (We are often told
> >     by one gtk+ member that some signal is private don't bother
> >     wrapping it, then we go to the tutorial and find an example
> >     that hinges on that function being public.  Nothing should
> >     be truely private unless no derived class can see or use it,
> >     thus those private things really should just be thought of
> >     as protected and we must wrap them.)
> 
> signals that are "private" usually shouldn't be signals, why
> should they if you're not supposed to connect a handler to it.
> i'm actually a bit confused about your terminology here, we don't
> really introduce "public" and "private" signals, we just make
> a distinction between signals that have to be emitted from
> an object's implementation (usually because there's important
> pre-/post-processing necessary) and signals that may be emitted
> randomly by the object user on his own behalf.

It is those signals that should be for the objects implementation
that are a fun to export.  Since our objects can derive very
easily, the functions on those signals should be available.  

The problem here is that any signal the user should want to 
hook into should not be called by gtk_signal_emit, but 
by an emit front.  But in the examples, (which we convert to
make sure ours is close) we find signals with no emit front
called.  

And since there also is not way to know if something is
internal or external for a signal, we are constantly surprised
to find the internal ones hooked onto in user programs.  Thus
we must conclude that all signals should be visible to the
user and some should be emittable.  (thus we have an emit/noemit
flag in our wrapper.)  

It is such an inconsistent set, we just have to guess. 
A header file indication would help greatly.
   
> > These are all done via convention in gtk+, but they are broken
> > many times.  Every time they were broken we had to add another
> > field parameter to our system.  At last count we had to recognize
> > 9 different parameters which combined to form over 20 possible
> > varients (many are mutually exclusive)
> 
> if you encounter places where gtk conventions/constraints are being
> broken, special caseing them in your language binding is the worst
> thing you can do. the correct way to handle such a situation is to
> report the brokeness and fix things up in gtk. we don't come up
> with random conventions late friday nights to get fun out of
> breaking them.

We do report them when we realize they are special cases (used
once), but sadly we don't often know the special cases from
the normal use.  If I find that 10 signals in 3 widgets
are different, I just conclude that was more usual use of
the signal, hence another pattern!

(Don't worry to much though as we needed some of those special cases 
just because gtk+ names are chosen badly so they hash in to C++ names.  
Like gtk_widget_map -> map (STL container)  gdk_rectange_union -> union
(C keyword).  Those make for enough fun! :-)
   
[...]
> > > we can't get signal connections going without that and can't get proper
> > > destruction (with weak reference callbacks as gtkobject has them) going
> > > without that either.
> > 
> > I was thinking more allong the line of a multiple inheritance system
> > where the base size was 4 bytes.  (pointer to the class)  This is
> > below an object.  Sets of bases can be combined through SI or virtual MI.
> > Although it is easier to define things that are always MI.  (thus
> > preventing the problems that C++ gets into of having multiple copies
> > within the classes.  Okay this is hard to imagine... I will
> > compose a small sample system this weekend with those properties to
> > give you an idea what I mean. 
> 
> multiple inheritance will definitely not be going into the libgobject
> logic, for one this is an extremely tedious thing to imlement in C
> efficiently and complexifies structure accesses by a significant
> amount, and for another the existing GtkObject system would be really
> hard to get going on top of that, if at all.
> and finally i guess there'd be some non-C++ language binders who
> are going to rip our asses off for that ;)

So even if I come up with an elegant and transparent system
it wouldn't be considered?  I don't think non-C++ language binders
would care how the data so long as it is available...

Ie. To get the data Bin data from a Container.

 GtkBin *bin=GTK_BIN(con); /* bin gives a different address. */

It is then just a matter of having offsets for data as well
as offsets in the class structure for multiple interface. 

--Karl 



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