[racket] [FFI] _union and define-cstruct

From: Laurent (laurent.orseau at gmail.com)
Date: Sat Oct 27 04:02:35 EDT 2012

On Fri, Oct 26, 2012 at 10:26 PM, Matthew Flatt <mflatt at cs.utah.edu> wrote:

> That seems like an ok solution.
>
> I would be tempted to write
>
>  (define-cstruct _XEvent ([type _int]))
>
>  (define-cstruct (_XAnyEvent _XEvent) ([serial _ulong]
>                                        ....))
>  (define-cstruct (_XKeyEvent _XEvent) ([serial _ulong]
>                                        ....))
>  ....
>
> Those declarations more directly fit the sub-structuring that is
> implemented by the union in "Xlib.h", but it doesn't give you
> `XAnyEvent-type', `XKeyEvent-type', etc., and the size of `_XEvent'
> isn't the maximum of the variant sizes.
>

Ok, so as Jon pointed out, the last part may be a problem then.
And _union is not the right thing to use here apparently.

Now I think that Jon's solution is actually quite good.
The XNextEvent* procedure does all that is needed (add the correct
pointer-tag) for the user, who can then use the corresponding "sub-struct"
on the event.
I'm just wondering if it would not be possible to simply add all relevant
tags to the any XEvent, e.g.:
(define (make-dummy-XEvent)
    (let ((s (malloc _int (* 24 (ctype-sizeof _long)))))
      (memset s 0 24 _long)
      (cpointer-push-tag! s XEvent-tag)
      (cpointer-push-tag! s XAnyEvent-tag)
      (cpointer-push-tag! s XKeypressedEvent-tag)
      ....
      s)
without caring about the actual kind of event received, and let the user
use the event kind it wants. But it's probably not so important now.

Thanks for your answers, I understand it better now.

Laurent


>
> At Fri, 26 Oct 2012 19:00:01 +0200, Laurent wrote:
> > Oooohh, I think I understand now: the way it was is already sufficiently
> > general.
> > The writer of the initial code took a different direction.
> > Instead of defining a union type, he changes the tag of the pointer
> > depending on what kind of type he needs in the union:
> > (cpointer-push-tag! e XAnyEvent-tag)
> > (case (XAnyEvent-type e)
> >     ((KeyPress) (cpointer-push-tag! e XKeyPressedEvent-tag))
> >     ((KeyRelease) (cpointer-push-tag! e XKeyReleasedEvent-tag))
> >     ....
> >
> > It's pretty smart. Is it the right way to go in general, and should
> _unions
> > be avoided?
> >
> > Laurent
> >
> > On Fri, Oct 26, 2012 at 6:39 PM, Laurent <laurent.orseau at gmail.com>
> wrote:
> >
> > > Hi,
> > >
> > > I am trying to convert an FFI cstruct definition into a union.
> > > More exactly, the previous definition was :
> > > (define-cstruct _XEvent
> > >     ((type EventType)))
> > >
> > > with EventType being defined elsewhere.
> > > But this was an incomplete definition, and I now want to translate the
> > > following C union:
> > > typedef union _XEvent {
> > >         int type;        /* must not be changed; first element */
> > >     XAnyEvent xany;
> > >     XKeyEvent xkey;
> > >     // ... the rest for later
> > > } XEvent;
> > >
> > > I searched the collects directory, but I see only a single and too
> simple
> > > _union use, so I'm not sure how to use it.
> > > I guessed the following:
> > >   (define _XEvent
> > >     (_union EventType ; type
> > >             _XAnyEvent ; xany
> > >             _XKeyEvent ; xkey
> > >             ; etc.
> > >             ))
> > >   (define (XEvent-type ev) (union-ref ev 0))
> > >   (define (XEvent-xany ev) (union-ref ev 1))
> > >   (define (XEvent-xkey ev) (union-ref ev 2))
> > >
> > > However, now I don't use define-cstruct anymore (it would not work with
> > > _union, would it?), so I don't have all the -tag, -pointer, etc.
> bindings,
> > > which I need.
> > >
> > > What should I do ?
> > >
> > > Thanks,
> > > Laurent
> > >
> > >
> > ____________________
> >   Racket Users list:
> >   http://lists.racket-lang.org/users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20121027/84e2b2eb/attachment.html>

Posted on the users mailing list.