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? Liam On Fri, Apr 18, 2014 at 2:01 PM, Cyrus Harmon <ch-l...@bobobeach.com> wrote: > > So I've been trying to get FSBV working on ABCL and I've run into a > problem with returning structs. The problem is that we allocate memory on > the stack for the return struct, successfully call the foreign function, > writing the return value into the appropriate place, then we free the > memory and return a pointer to the now defunct memory location. > > I'm curious as to how this is supposed to work in other implementations. > It obviously does work in, at least, SBCL, so I must be doing something > wrong. But looking at the ffcall-body-libffi function it looks like we > setup the foreign memory for RESULT in with-foreign-objects and then if we > have a translatable-foreign-type, we return RESULT, which of course gets > freed by with-foreign-objects. What am I missing here? > > thanks, > > Cyrus > > > (defun ffcall-body-libffi > (function symbols return-type argument-types &optional pointerp (abi > :default-abi)) > "A body of foreign-funcall calling the libffi function #'call > (ffi_call)." > (let ((number-of-arguments (length argument-types))) > `(with-foreign-objects > ((argvalues :pointer ,number-of-arguments) > ,@(unless (eql return-type :void) > `((result ',return-type)))) > (loop :for arg :in (list ,@symbols) > :for count :from 0 > :do (setf (mem-aref argvalues :pointer count) arg)) > (call > (prepare-function ,function ',return-type ',argument-types ',abi) > ,(if pointerp > function > `(foreign-symbol-pointer ,function)) > ,(if (eql return-type :void) '(null-pointer) 'result) > argvalues) > ,(if (eql return-type :void) > '(values) > (if (typep (parse-type return-type) 'translatable-foreign-type) > ;; just return the pointer so that expand-from-foreign > ;; can apply translate-from-foreign > 'result > ;; built-in types won't be translated by > ;; expand-from-foreign, we have to do it here > `(mem-aref result ',return-type)))))) > _______________________________________________ > Cffi-devel mailing list > Cffi-devel@common-lisp.net > http://common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel >
_______________________________________________ Cffi-devel mailing list Cffi-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/cffi-devel