Re: New 'GObject' as base for GtkObject?



> On Thu, 9 Dec 1999, Karl Nelson wrote:
> 
> > 
> > Tim, 
> > 
> > I think this is definitly the right track.  But is does miss
> > one of Guillaume's points, consistancy.  It is not necessary to
> > work in a language that forces it, but if a simple macro format
> > converted a base format (like the gtkprocess header generator)
> > was provided it would at least ensure the object system was
> > easier to use and more consistantly applied.  
> 
> hum, i don't think i understand what you are talking about here
> (though i haven't paid close attention to all of guillaume's posts
> because of language bashing that went on there).

I am not sure how much was language bashing (although Guillaume style 
is a bit abrasive).  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.

> 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)
  - 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.)
  - the same arguments shared between signal and emit functions,
    and the virtual function.
  - 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.)

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 mutially exclusive)
  


Gtkprocess was the experimental spin off 
of the gtkmmproc program.  I was experiementing with making a 
simple gtk+ header generation.  Owen gave me some comments on it 
and what problems he had with it, but I got busy and didn't get
to revising it to version 2.  (I found the information I needed
from it already: m4/lex/yacc beats perl hands down for code
generation even if it is ugly.)

I have version 1 still floating arround.  It does not
have the consistancy I am requesting because it was trying to
match gtk+ and all of its wild constructions.

http://www.ece.ucdavis.edu/~kenelson/private/gtkprocess.tar.gz

> > Minor comments...
> > 
> > > - support for per-object quark data (the base GObject shouldn't
> > >   take up more than 12 bytes, i.e. a class pointer, reference count
> > >   and a GData* pointer)
> > 
> > I don't see why it even needs more than the class pointer.  The
> > data and reference pointer could be added in a type derived from
> > the base object if size was really an issue.  
> 
> personally i consider the quarked data a standard feature we should provide
> there, especially to avoid hackery in class tress that derive from a GObject
> without quarked data and figure the need for quarked data later on. those
> class trees would probably end up using g_dataset_* functionality and would
> then need support for dataset destruction in the base class (to invalidate
> the object's dataset entry once the pointer is freed).
> apart from that, support for datalists is simply required if we want the
> signal system seperated as well, there'd be no facility to store the
> object's handler list otherwise.
> on the reference counting, that is also a definite requirement for GObject,
> 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. 

> > 
> > It will never be possible to fill all the holes, but 
> > just knocking off the major ones would make life a lot better.  
> > However, consistant use of the object system would do
> > more for us than the actual design.  The Gtk-- and Libsigc++
> > project members woould be happy to lend support.
> 
> having a more lightweight base object could certainly help that,
> for instance looking at the GdkDrawablePrivate struct in gtk 1.3,
> which has a class function pointer, reference counting and
> a user_data pointer, i see a perfect candidate for a GObject derivative.

I haven't looked over it yet, but from earlier conversations 
I trust that you are correct.  Just having a good base like
that would help.

OFF TOPIC

I have been wondering something about the gtk+ tool set.  I notice
that the concept of a virtual function and a signal are very closely
tied, but at the same time they appear seperately in a wealth of 
combinations.  Part of this is because the signal has a pointer to
the function that is virtual, but then it has flags for before, after
and other fun things.  

In effect this is the opposite of Qt.  In Qt the vfunc is provided
by the language and then calls the signal from the vfunc.  This allows
you the freedom to chose to call the signal or not, and to chose
the order of calling without all those flags.

Ie.  (C++ish psuedo code)

  Foo is the base object with a signal for some action and a virtual
  function.  The virtual funciton does the action and the signal informs
  others (external to the widget) of the change...

   class Foo
     {
      signal int state_changed(int);
      virtual int set_state(int );
     } ;

   int Foo::set_state(int i)
     {
      /* do before emit stuff */
      rc=state_changed.emit(i);
      /* do after emit stuff */
      return something; /* can be rc or its own choice */
     }

  It is clear here there is no need for CALL_AFTER or CALL_BEFORE,
  both are applicable.  Thus things are simpler.

  Bar comes allong and wants to change the implementation of 
  set_state.

  class Bar : Foo
    {
      virtual int set_state(int) 
    };

  It can chose to call the old...

  int Bar::set_state(int i)
     {
       /* Bar stuff */
       Foo::set_state();  /* let Foo emit signal */
     }

  Or chose to just skip the other...

  int Bar::set_state(int i)
    {
      /* Bar stuff */
      state_changed.emit(i); /* skip Foo and just inform */
    }
  

Would it not have been simpler to have defined a signal and vfunc
seperately  and in a more flexible relationship?  Was this
intention to do the opposite of Qt or was this never thought about?
I am not proposing that this be done, it would be a huge
headache to change and not worth much at this point.  Still
I found the differences between the two striking. 

--Karl



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