[racket] [FFI] _union and define-cstruct
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