[racket] [FFI] _union and define-cstruct

From: Jon Rafkind (rafkind at cs.utah.edu)
Date: Fri Oct 26 17:17:37 EDT 2012

Actually I think I know why it is like the way it is now..

To get an X11 event you pass in an XEvent* to XNextEvent which copies the event to the input pointer. Essentially

void XNextEvent(XEvent * input){
  switch (event_type){
    case Keyboard: {
        XKeyboardEvent real_event;
        memcpy(input, real_event, sizeof(real_event));
        break;
    }
    case Mouse: ...
    ...
  }
}

So the input event structure must be large enough to support any event and you can't know before hand what kind of event XNextEvent will output. Well I suppose you could use XPokeEvent somehow.. But in any case the XEvent cstruct is large enough to hold any kind of specific event.

On 10/26/2012 03:06 PM, Jon Rafkind wrote:
> I agree with this. The code Laurent is talking about is my x11 ffi bindings. Laurent, feel free to make this change and push to the repo. I'm not sure why I didn't use the super struct thing to begin with, maybe it didn't exist when I initially wrote the bindings.
>
> https://github.com/kazzmir/x11-racket for anyone interested.
>
> On 10/26/2012 02:26 PM, Matthew Flatt 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.
>>
>> 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
>> ____________________
>>   Racket Users list:
>>   http://lists.racket-lang.org/users
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users


Posted on the users mailing list.