Re: Initialisation/Finalisation



        Humph. I've been using Gtk for about a year for
the UI part of my work and started writing widgets by
copy-paste-edit. 

Sorry to be so critical, but it seems that creating a fairly simple
gobject is not easy for a first time user.

        Just the other week I wrote my first GObject
derivitive from-scratch. Yes the doc is incomplete and
that makes it _very_ complicated for the first time user.

4.    G_OBJECT_CLASS (parent_class)->finalize (object);

      By reading other examples in the docs, I take it that
      parent_class is a static (file scoped) variable, (not a member
      of any struct).  It seems odd to me that such a loose variable
      should be necessary, when everything else is nicely encapsulated
      either in the class or object variables.


        The parent_class is a pointer to the parent class and 
I think it's just a "lazy" variable. its resolved in the class init
function (g_type_somethingorother_peek_parent()) but I believe that 
you can still access it through the instance of your object. 
something like:
parent_class = G_OBJECT_CLASS(G_MYTYPE_INSTANCE_GET_CLASS(instance));

3.    Why is it necessary to bother about the

       object_class->finalize = finalize;

      line, when there is a field in the Typeinfo structure to specify
      the finalise function.  Is it necessary to specify it twice?  If
      so, it seems a bit precarious to me.

        Right now in gtk all widgets are derivitives of the GObject. 
We want to use the the reference count mechanism from the GObject so
when an object needs to "uninit" stuff than he should "chain" the
finalize
so that the derived object user can destroy it with "g_object_unref()". 
        The complications here also seem to stem from the fact that
we use the same api to build GObject derived types as well as
fundamental
types.

1.   /* And override the finalize method here */
     static void
     class_init (PGCClass *klass)

     I take it your typo was in the comment rather than the code?

I believe what he meant was: in the class_init func (in which you
recieve
memory containing the parent class which you are responsable the
initialize
with g_type_object_peek_parent()) if you want to chain the finalize
function
from the GObjectClass; this is the place to do it. this will override
part of
your copy of "that class". Actually all overrides should be done in
class_init.


Hmmm I hope this helped you at least a little.
        -Tristan



John Darrington wrote:

Well thanks for the response.  Unfortunately it raises more questions
for me than answers.  First, the philosphical ones:

1.   /* And override the finalize method here */
     static void
     class_init (PGCClass *klass)

     I take it your typo was in the comment rather than the code?

2.    static void   finalize (GObject *object)

      This is a CLASS finalize function, yes?  Why therefore does it
      take an OBJECT as it's argument?  This seems especially
      inconsistent, when the class_init function takes a CLASS.

3.    Why is it necessary to bother about the

       object_class->finalize = finalize;

      line, when there is a field in the Typeinfo structure to specify
      the finalise function.  Is it necessary to specify it twice?  If
      so, it seems a bit precarious to me.

4.    G_OBJECT_CLASS (parent_class)->finalize (object);

      By reading other examples in the docs, I take it that
      parent_class is a static (file scoped) variable, (not a member
      of any struct).  It seems odd to me that such a loose variable
      should be necessary, when everything else is nicely encapsulated
      either in the class or object variables.

And the practical demo:

1.    When I put the code in that you suggested I get the following
      run time messages:

 (process:9485): GLib-GObject-WARNING **: class finalizer specified for static type `PGClient'

 (process:9485): GLib-GObject-WARNING **: class finalizer specified for static type `PGClient'

 (process:9485): GLib-GObject-CRITICAL **: file gobject.c: line 588 (g_object_new): assertion 
`G_TYPE_IS_OBJECT (object_type)' failed

 (process:9485): GLib-GObject-WARNING **: invalid cast from (NULL) pointer to `<invalid>'

 ** ERROR **: file pgclient.c: line 68 (pgclient_new): assertion
    failed: (pg)

2.    So I replaced the ClassFinaliseFunc pointer in the typeinfo
      struct (see point 3. above) to see what happens.  This time,
      there's no run time errors, but the finalize func never gets
      called (as evidenced by a g_print() diagnostic that I put in.

Sorry to be so critical, but it seems that creating a fairly simple
gobject is not easy for a first time user.

J'



On Tue, Nov 05, 2002 at 10:29:51AM +0000, iain wrote:
     On Mon, 2002-11-04 at 12:18, John Darrington wrote:
     >
     > My Questions are:
     >
     > 1. The Finalize func undoes the Init func.  Fair enough.  But why is
     >    there no GInstanceFinalizeFunc?  See example below:

     All objects I've ever written have had NULL for everything except the
     GClassInitFunc and GInstanceInitFunc.

     Actually I think I had one that had NULL for GInstanceInitFunc too once.
     So basically, you don't need to worry about them.

     >
     > I have a gobject, whose _new function looks like :
     >
     > GObject*
     > pgc_new(const gchar *c)
     > {
     >   PGC *pg;
     >
     >   pg = PGC(g_object_new(TYPE_PGC,0));
     >
     >   g_assert(pg);
     >
     >   pg->info = g_strdup(c);
     >
     >   return G_OBJECT(pg);
     >
     > }
     >
     >
     > Now the doco for g_strdup says that the pointer returned must be freed
     > when no longer needed.  But how and when can I do that ??  It needs to
     > be freed when the object is destroyed, but there is no
     > GInstanceFinalizeFunc which (to me) would seem the logical thing to
     > have.
     >

     Override either the dispose or the finalize methods of the GObjectClass

     like so.

     static void
     finalize (GObject *object)
     {
        PGC *pg;

        pg = PGC(object);

        g_free (pg->info);

       /* Other things here */

       /* Chain up to the parents finalize */
       G_OBJECT_CLASS (parent_class)->finalize (object);
     }

     /* And override the finalize method here */
     static void
     class_init (PGCClass *klass)
     {
       GObjectClass *object_class;

       object_class = G_OBJECT_CLASS (klass);

       object_class->finalize = finalize;
     }

     Now whenever the object is destroyed, the memory will be freed.

     iain
     --
     "This way of life is so devised,
      To snuff out the mind that moves"



--
PGP Public key ID: 1024D/2DE827B3
fingerprint = 8797 A26D 0854 2EAB 0285  A290 8A67 719C 2DE8 27B3
See http://www.keyserver.net or any PGP keyserver for public key.

  ------------------------------------------------------------------------
   Part 1.2Type: application/pgp-signature



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