Hi everyone,
I put in a solution for the Rosetta task to create a Hello, World window with X11.
I simply translated the C solution, reproducing its behavior exactly.
This requires the latest TXR 180 because it uses unions.
I define XEvent as a union, just like in C, and it is extracted by pointer using the XEvent function.
There is a slight clunkiness in dealing with unions because of their inherent lack of safety:
(while t
(let ((e (make-union (ffi XEvent)))) ;; explicitly make union
(XNextEvent d e)
(caseql* (union-get e 'type) ...))) ;; explicitly convert desired member
The FFI union type requires an argument of type union, with the same tag such as XEvent.
The union e here allocates a buffer for the C union, based on knowing the size from the FFI type.
XNextEvent is defined as:
(deffi XNextEvent "XNextEvent" int (Display (ptr-out XEvent)))
Where XEvent is a union type:
(typedef XEvent (union _XEvent
(type int)
(pad (array 24 long))))
It has only two members: type and pad; more could be added, but I didn't need them for this sample.
Unions can be passed to functions by value quite perfectly well, but XNextEvent needs a pointer; so the argument is a ptr-out, reflecting that XNextEvent isn't receiving values from the union; it is just filling it in.
After XNextEvent fills in the union, it's up to the program to know which union member can be accessed. That's the job of the expression (union-get e 'type) which retrieves the type member to get at the event type. I.e. the memory is treated as the type member, which has type int, and so an integer is retrieved.
For struct types and arrays, conversion between the Lisp realm and the C representations is automated.