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

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

g-wrap <gw-guile-wct> questions


From: Steve Tell
Subject: g-wrap <gw-guile-wct> questions
Date: Thu, 12 Aug 2004 23:51:31 -0400 (EDT)

There's a simple C library that I'm trying to g-wrap for use with
guile.  While I have somthing kind of working using g-wrap-1.9.1, I
have a bunch of questions.


The library uses a somewhat object-oriented C style.  A "constructor"
mallocs a structure and allocates resources that are stored in the
structure.  On success, a pointer to this structure is returned; on
failure NULL is returned and errno is set.

The library has various functions that operate on the data structure,
all of which take as an argument the pointer returned by the
constructor.  (most of them involve lots of ioctls on the file
descriptor held in the object)

Lastly, the library has a "close" routine or destructor which takes
the pointer returned by the constructor, frees up system resources in
the structure, and calls free() to free up the structure itself.  The
user of the library obviously must not use the pointer after calling
the destructor.

A stripped-down fragment of the library looks like this:

struct parport *parport_open_device(char *dev)
{
        int fd;
        struct parport *pp;
        pp = (struct parport *)calloc(1, sizeof(struct parport));
        pp->fd = open(dev, O_RDWR|O_NONBLOCK);
        if(pp->fd < 0) return NULL;
        pp->device = strdup(dev);
        return pp;
}

void
parport_close_device(struct parport *pp)
{
        close(pp->fd);
        free(pp->device);
        free(pp);
}


I've got some of this working using "wrap-as-wct!"  by following
g-wrap-1.9.1's test/test-child-spec.scm.  Part of my spec file looks
like:

(define-class <devparport-wrapset> (<gw-wrapset>)
  #:id 'devparport-wrapset
  #:dependencies '(standard))

(define-method (global-declarations-cg (ws <devparport-wrapset>))
  (list
   (next-method)
   "#include \"libparport.h\"\n"))

(define-method (initialize (ws <devparport-wrapset>) initargs)
  (next-method)

  (wrap-as-wct! ws
                #:name '<gw:parport*>
                #:c-type-name "struct parport*"
                #:c-const-type-name "const struct parport*")

  (wrap-function! ws 
                  #:name 'parport-open-device
                  #:returns '<gw:parport*>
                  #:arguments '(((mchars caller-owned) device))
                  #:c-name "parport_open_device"
                  #:description "Opens parport and returns handle")

  (wrap-function! ws 
                  #:name 'parport-close
                  #:returns 'void
                  #:arguments '((<gw:parport*> p))
                  #:c-name "parport_close_device"
                  #:description "Close handle to parallel port device")
)

(define-class <devparport-gwrap> 
  (<devparport-wrapset> <gw-guile-wrapset>)
  #:id 'devparport-gwrap)

(define-method (initialize (ws <devparport-gwrap>) initargs)
  (next-method ws (append '(#:module (device parport)) initargs)))
(generate-wrapset 'guile 'devparport-gwrap "parport")


Questions: 

- 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?

Could this be done by nulling out the "pointer" in the
wrapped_c_pointer_data structure pointed to by the wct smobs? Or could
there be many copies of that running around with the same pointer value?


- 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.


- 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?


- I'd really like to have the guile version of this library construct and
use goops objects, so I can inherit from and extend it.
Do I have to wrap the C library into a module of non-goops guile procedures
and then write a goops-using module that builds the objects and methods
using the g-wrapped module?
Or can g-wrap help in creating goops classes, objects and methods with 
less intermediate glue required?

I suppose an alternate might be to rewrite the C library using gobject
and get into guile-gnome-gobject.  While that's on my list of things
to learn about, I might not want this little library's guile wrapping
to depend on guile-gnome.


Since the wrapped-C-pointer use of g-wrap isn't covered well in the g-wrap 
documentation, figuring this out might serve as a useful example. (hint)

thanks!
Steve





reply via email to

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