g-wrap and glib container types...

Rob Browning rlb@cs.utexas.edu
06 Nov 2000 14:41:10 -0600

Robert and I have been trying to figure out how to handle glib
container types (like GList, GSList, GArray, GHashTable, etc.) cleanly
from g-wrap.  Last time I thought hard about this, I thought I wanted
to teach g-wrap how to handle these things directly, but I've since
changed my opinion to be closer to what (I think) Robert was

Consider the function

  GArray* frob_accounts(GList *accounts);

Conceivably you might want to be able to call this from the scheme side
by passing it a GList* pointer-token, or a regular scheme list of
Account* pointer-tokens.  Likewise, sometimes you might just want it
to return a GArray* pointer-token, and sometimes you might want a
scheme array.

Because of the variety of possible desires, and because we don't want
to have to have a bunch of different functions on the scheme side call
the same C side function but with different parameter/return value
semantics, I now agree with Robert (presuming that I'm recalling his
argument correctly) that we should just go the "helper conversion
function" route.

The idea is that the g-wrapped functions will still deal exclusively
with pointer-tokens on the scheme side, but we'll also provide
converter functions like glib-glist->list and list->glib-glist that
will allow you to perform whatever conversions you'd want.  Since
there's no way, in general, to know what types are being held inside a
glib container (since C's not a dynamically typed language), the
converter functions will have to accept arguments telling them what
you want.  So you might say:

  (let* ((acclist (list acct-1 acct-2 acct-3))
         (g-array (frob-accounts (list->glib-glist 'Account* acclist))))
    (glib-garray->vector 'Account* g-array))

Of course, we'd also have to wrap up the cleanup functions so that you
could clean up the GList*'s etc. when appropriate, either that, or we
could add a flag to the converters that tells them whether or not to
destroy their argument. i.e., presuming that frob-accounts returns a
newly allocated GArray* that the caller's expected to take
responsibility for we would have either this

  (let* ((acclist (list acct-1 acct-2 acct-3))
         (g-array (frob-accounts (list->glib-glist 'Account* acclist)))
         (result (glib-garray->vector 'Account* g-array)))
    (garray-destroy g-array)

or, if we added a cleanup-arg? argument to the converter instead:
  (let* ((acclist (list acct-1 acct-2 acct-3))
         (g-array (frob-accounts (list->glib-glist 'Account* acclist))))
    (glib-garray->vector 'Account* #t g-array))

Rob Browning <rlb@cs.utexas.edu> PGP=E80E0D04F521A094 532B97F5D64E3930