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-lisp@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