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))))))