guile-gtk-general
[Top][All Lists]
Advanced

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

Re: g-wrap <gw-guile-wct> questions


From: Steve Tell
Subject: Re: g-wrap <gw-guile-wct> questions
Date: Mon, 16 Aug 2004 02:32:24 -0400 (EDT)

On Sun, 15 Aug 2004, Andy Wingo wrote:

> Hey Steve,
> 
> I'm not a wct expert. I usually use guile-gobject to handle that stuff,
> which uses a combination of GOOPS objects and SMOBs. However...
> 
> On Thu, 12 Aug 2004, Steve Tell wrote:
> 
> > - Can g-wrap help with the C destructor problem, preventing future
> > unwrapping of the C pointer that was wrapped at the call to the
> > constructor?  (Its important in this case to be able to explicitly
> > close objects created with the library, because they involve system
> > resources (like open file descriptors) that may need to be returned at
> > a particular time, instead of waiting for garbage collection.)  
> > Or would I have to add another layer of indirection somehow?
> 
> GtkObjects have this problem, because of the gtk_object_destroy
> procedure. It effectively does as you say, nulling out the pointer after
> unreffing, and the C part of the wrapper detects for a destroyed value,
> which will throw an error if a destroyed value is used.
> 
> This is possible because NULL is a magic value for the GObject wrapper;
> it claims to have a reference on an object, and you can't have a
> reference on NULL. Whether this is possible for WCT instances is as yet
> unspecified; is it useful to wrap NULL? I would guess not, although are
> there any counter-examples of the usefulness of a typed NULL?
> 
> FWIW, the wrap-value-cg in (g-wrap guile) seems to explicitly return #f
> for NULL values. So perhaps that's the intent.
> 
> > - Since in this case I have control over the library's source, I could
> > modify it to have seperate "close" and "free" routines.  How would I
> > connect the "free" routine to be called at GC time?  Based on the
> > documentation, I would think I would subclass <gw-guile-wct> and
> > provide a destruct-value-cg for it, but I can't seem to figure out how
> > to do that.  I've tried:
> > 
> >     (define-class <gw:parport*> (<gw-guile-wct>))
> >     (define-method (destruct-value-cg (t <gw:parport*>)
> >                                   (value <gw-value>)
> >                                   status-var)
> >       (list "parport_free(" (var value) ");\n"))
> > 
> > but get "Unbound variable: <gw-guile-wct>" in the define-class.
> 
> Hm. The unbound variable warning would be because (g-wrap guile) doesn't
> export the class. Perhaps that's an oversight, although in 1.3.4, WCT
> types were not extensible. Andreas?

I hacked a bit (both by changing g-wrap/guile.scm and by using module-ref) 
and was able be able to subclass <gw-guile-wct>, but any
attempts at destruct-value-cg and wrap-value-cg methods 
didn't have any effect on the C code generated by (generate-wrapset).

Puzzling over the source, I realized that wrap-as-wct! is hiding a (make
<gw-guile-wct> ... ) for the type object.  Replacing the call to
wrap-as-wct! with a hacked copy that does a (make <gw:parport*> ) does
result in my replacement -cg methods getting used.  
While I can affect the generated C - but so far I don't have the custom 
wrap-value-cg working.
 
> Regarding making a destroy-value-cg (s/destruct/destroy/ in 1.9.1), I
> think that's the correct solution. However, the current (g-wrap guile)
> doesn't pass a cleanup function to gw_wct_new, so such a function will
> never be called. However, the free function in guile-wct.c does free the
> data. You should probably change (g-wrap guile) to somehow hook the
> destroy-value function to the cleanup handler.

If I put a free() into the destroy-value-cg, I get bogus data in my
structure and an eventual core dump, so obviously that's wrong.
I'm still chasing this through g-wrap's internals trying to understand how 
the destroy-velue-cd relates to the cleanup function in
wrapped_c_type_data, but you've pointed me onto the right track.

> G-wrap makes my head hurt.

Yes, at first glance it doesn't look like all that much code.  But there's 
a lot going on in there.

 
> > - I might prefer that the guile wrapping of the library's "constructor"
> > either return the wrapped-C-type object or throw an error, instead of
> > returning #f for NULL pointers as it seems to do when using
> > "wrap-as-wct!".  It looks like this might be doable by providing an
> > alternate wrap-value-cg for this particular wrapped type; is this the 
> > right approach?
> 
> The exception approach is correct, I think, but I don't know about
> implementing it. Perhaps post-call-result-cg is what you want; see
> (gnome gw glib-spec) for an example (although it uses post-call-arg-cg,
> since GErrors are passed as arguments).

I got somthing limping along like this:

(define-method (wrap-value-cg (wct <gw:parport*>)
                              (value <gw-value>)
                              status-var)
  (let ((wct-var (slot-ref wct 'wct-var-name))
        (sv (scm-var value))
        (cv (var value)))
    (list
     "if(" cv " == NULL) scm_syserror_msg(\"wrap(gw:parport*)\", \"error 
~a\", SCM_EOL, errno);\n"
     "else " sv " = gw_wcp_assimilate_ptr((void *) " cv ", " wct-var 
");\n")))


(I'm doing the call to scm_syserror_msg wrong somehow; 
 I get "Exception during displaying of error: misc-error" but at least I 
get an error thrown)

 
> This code seems to be generally useful. Perhaps NULL should only be
> allowed as a return value if (null-ok) is in the typespec options.
> Otherwise it would throw an exception. Andreas?

I would think this (throwing error on NULL) is a common behavior that 
should be selectable or the default.
There could many forms that you'd like the error messsage to take though.
In my case I need it to include strerror(errno), but that won't always be 
the case.  Worse, different functions may need different styles
of error message.

Thanks for the hints, Andy.
I'm looking forward to any comments Andreas might have.


My earlier crude attempts can be seen here
http://www.telltronics.org/pub/guile/guile-device-parport-20040812.tar.gz
and is completely without any configuration or packaging support yet.

Its purpose is allowing guile programs to control hardware attached to a 
PC parallel port, assuming a linux-like /dev/parport driver.

 
Steve




reply via email to

[Prev in Thread] Current Thread [Next in Thread]