From ecls
;; The following is a straight port if the example in the Linux
;; select(2) manpage to the ECL FFI.
(defpackage "select-test"
(:use "CL" "FFI" "UFFI"))
(in-package "select-test")
(clines "#include <sys/select.h>")
(defun fdset-size ()
(c-inline () () :int "sizeof(fd_set)" :one-liner t :side-effects nil))
(defun select (infds)
;; fd_set is an opaque typedef, so we can't declare it locally.
;; However we can find out its size and allocate a char array of
;; the same size which can be used in its place.
(let ((fsize (fdset-size)))
(with-foreign-object (rfd `(:array :unsigned-char ,fsize))
; Reset fd sets
(c-inline (rfd) (:object :object) :void
"{ FD_ZERO(#0->foreign.data); }"
:one-liner nil
:side-effects t)
; ... and initialise them
(dolist (fd infds)
(c-inline (fd rfd) (:int :object) :void
"{ FD_SET(#0, (fd_set*)#1->foreign.data); }"
:one-liner nil
:side-effects t))
; Do select wait
(let ((retval
(c-inline (rfd) (:object :object) :int
"{ struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
@(return) = select(1, #0->foreign.data, NULL, NULL, &tv); }"
:one-liner nil
:side-effects t)))
; check return type
(case retval
(-1 (format t "error~%"))
(0 (format t "no data in 5 seconds~%"))
(otherwise (format t "Data available~%")))))))
;; Quick test code on (load ..)
(format t "fd_set is ~A~%" (fdset-size))
(select '(0))