Calling a struct-by-value by reference

Liam Healy lnp at healy.washington.dc.us
Wed Dec 23 03:29:36 UTC 2015


Hi Attila,

Re: https://bugs.launchpad.net/cffi/+bug/1528719

(There is an error in the sample code, the struct is called
'struct-pair, not 'pair.)
Here is a simpler exhibition of the problem

(sumpair (convert-to-foreign '(40 . 2) '(:struct struct-pair)))
The value #.(SB-SYS:INT-SAP #X7FFFEC003560) is not of type LIST.
   [Condition of type TYPE-ERROR]

So, you've said the function is call-by-value, and then you want to
pass a pointer to the structure, and it makes sense there's an error.
You have to assume a translator, because that's the only way to have a
structure by value.

I understand the desire to be able to pass a pointer instead, but my
approach would be different. I'd change the function argument
definition and extend the syntax to say that you're going to pass a
pointer, e. g.

(defcfun "sumpair" :int
       (p (:struct struct-pair) :pointer))

which I would have expand to something like

 (DEFUN SUMPAIR (P)
       (WITH-FOREIGN-OBJECTS ((CFFI::ARGVALUES :POINTER 1) (CFFI::RESULT ':INT))
         (MEM-REF
          (PROGN
            (LOOP :FOR CFFI::ARG :IN (LIST P)
                  :FOR
                  COUNT :FROM 0
                  :DO (SETF (MEM-AREF CFFI::ARGVALUES :POINTER COUNT)
CFFI::ARG))
            (CFFI::CALL
             (CFFI::PREPARE-FUNCTION "sumpair" ':INT '((:STRUCT STRUCT-PAIR))
                                     ':DEFAULT-ABI)
             (FOREIGN-SYMBOL-POINTER "sumpair") CFFI::RESULT CFFI::ARGVALUES)
            CFFI::RESULT)
          :INT)))

So now you can do
     (sumpair (convert-to-foreign '(40 . 2) '(:struct struct-pair)))
     42

I don't like the idea of hacking up translate-into-foreign-memory
because you're doing extra work that way, and as you can see, the
expansion can be simpler than the translated case. The only
disadvantage of this approach is that you'll have to have two
different functions if you will be calling the same function with a CL
object and with a foreign pointer. I imagine that this won't happen
very often; I'm guessing this is for chaining together foreign calls
in CL, where the foreign structure never sees the light of day (=lisp
form).

(The defcfun won't expand the way I've shown yet, but the
pseudo-expansion actually can be compiled and run.)

What do you think?

Liam



More information about the cffi-devel mailing list