Hi,
I'm working on an epoll interface, but having trouble with nested
structs. Below code snippet is just a minor example where things
explode. Does anybody have an idea about what I might be missing?
Regards.
(defmacro prog1-let ((var val) &body body)
`(let ((,var ,val))
,@body
,var))
(defmacro maybe-error (test)
(let ((errno (gensym)))
`(when ,test
(let ((,errno *errno*))
(error (foreign-funcall "strerror" :int ,errno :string))))))
(defcvar "errno" :int)
; typedef union epoll_data {
; void *ptr;
; int fd;
; __uint32_t u32;
; __uint64_t u64;
; } epoll_data_t;
(defcstruct data
(ptr :pointer)
(fd :int)
(u32 :uint32)
(u64 :uint64))
; struct epoll_event {
; __uint32_t events; /* Epoll events */
; epoll_data_t data; /* User data variable */
; };
(defcstruct event
(events :uint32)
(data data))
; int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
(defcfun "epoll_ctl" :int
(epfd :int)
(op :int)
(fd :int)
(event (:pointer event)))
(defun control (epfd op fd events)
(with-foreign-object (event-ptr 'event)
;; Set `EVENTS' slot of the `EVENTS'.
(setf (foreign-slot-value event-ptr 'event 'events) events)
;; Empty `DATA' slot of the `EVENTS', and set `FD' slot of the `DATA'.
(let ((data-ptr (foreign-slot-pointer event-ptr 'event 'data)))
(setf (foreign-slot-value data-ptr 'data 'ptr) 0
(foreign-slot-value data-ptr 'data 'u32) 0
(foreign-slot-value data-ptr 'data 'u64) 0
(foreign-slot-value data-ptr 'data 'fd) fd))
(prog1-let (res
(foreign-funcall
"epoll_ctl"
:int epfd :int op :int fd :pointer event-ptr
:int))
(maybe-error (minusp res)))))
; in: DEFUN CONTROL
; (SETF (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::PTR)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::U32)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::U64)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::FD)
; EPOLL::FD)
; --> PROGN SETF LET* MULTIPLE-VALUE-BIND LET PROGN CFFI::FOREIGN-SLOT-SET
; --> SETF LET* MULTIPLE-VALUE-BIND LET PROGN CFFI::MEM-SET
; --> CFFI-SYS:%MEM-SET LET SETF SB-KERNEL:%SET-SAP-REF-32
; ==>
; EPOLL::DATA-PTR
;
; note: deleting unreachable code
; (EPOLL::PROG1-LET
; (EPOLL::RES
; (CFFI:FOREIGN-FUNCALL "epoll_ctl" :INT EPOLL::EPFD :INT EPOLL::OP :INT
; EPOLL::FD :POINTER EPOLL::EVENT-PTR :INT))
; (EPOLL::MAYBE-ERROR (< EPOLL::RES 0)))
; --> LET
; ==>
; EPOLL::RES
;
; note: deleting unreachable code
; (SETF (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::PTR)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::U32)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::U64)
; 0
; (CFFI:FOREIGN-SLOT-VALUE EPOLL::DATA-PTR 'EPOLL::DATA 'EPOLL::FD)
; EPOLL::FD)
; --> PROGN SETF LET* MULTIPLE-VALUE-BIND LET PROGN CFFI::FOREIGN-SLOT-SET
; --> SETF LET* MULTIPLE-VALUE-BIND LET PROGN CFFI::MEM-SET
; --> CFFI-SYS:%MEM-SET LET SETF
; ==>
; (SB-KERNEL:%SET-SAP-REF-SAP EPOLL::DATA-PTR 0 #:VALUE174)
;
; caught WARNING:
; Asserted type SB-SYS:SYSTEM-AREA-POINTER conflicts with derived type
; (VALUES (INTEGER 0 0) &OPTIONAL).
; See also:
; The SBCL Manual, Node "Handling of Types"
;
; compilation unit finished
; caught 1 WARNING condition
; printed 2 notes