My first cut at this makes me think that the translate-from-foreign and w-f-o should trade places. Here's a selected macroexpansion of GSLL's cx-add:
(LET ()
(DEFUN CX-ADD (C1 C2)
(DECLARE)
(LET ((#:CRETURN
(WITH-FOREIGN-OBJECT (#:G1705 '(:STRUCT GRID:COMPLEX-DOUBLE-C))
(TRANSLATE-INTO-FOREIGN-MEMORY C1
#<GRID::COMPLEX-DOUBLE-TYPE
GRID:COMPLEX-DOUBLE-C>
#:G1705)
(WITH-FOREIGN-OBJECT (#:G1706 '(:STRUCT GRID:COMPLEX-DOUBLE-C))
(TRANSLATE-INTO-FOREIGN-MEMORY C2
#<GRID::COMPLEX-DOUBLE-TYPE
GRID:COMPLEX-DOUBLE-C>
#:G1706)
(TRANSLATE-FROM-FOREIGN ;;; <=========== this should be after the next two lines
(WITH-FOREIGN-OBJECTS ((CFFI::ARGVALUES :POINTER 2)
(CFFI::RESULT '(:STRUCT GRID:COMPLEX-DOUBLE-C)))
(LOOP :FOR CFFI::ARG :IN (LIST #:G1705 #:G1706)
:FOR
COUNT :FROM 0
:DO (SETF (MEM-AREF CFFI::ARGVALUES :POINTER COUNT) CFFI::ARG))
(CFFI::CALL
(CFFI::PREPARE-FUNCTION "gsl_complex_add"
'(:STRUCT GRID:COMPLEX-DOUBLE-C)
'((:STRUCT GRID:COMPLEX-DOUBLE-C)
(:STRUCT GRID:COMPLEX-DOUBLE-C))
':DEFAULT-ABI)
(FOREIGN-SYMBOL-POINTER "gsl_complex_add") CFFI::RESULT CFFI::ARGVALUES)
CFFI::RESULT)
#<GRID::COMPLEX-DOUBLE-TYPE GRID:COMPLEX-DOUBLE-C>)))))
#:CRETURN))
(MAP-NAME 'CX-ADD "gsl_complex_add")
(EXPORT 'CX-ADD))
So that means some mashing around the other definitions, as the translate-from-foreign comes in outside the ffcall-body-libffi. As to why it works in SBCL (and maybe CCL): um, luck?