[Openmcl-devel] Calling foreign function with float array as argument?

Ronnie Hoogerwerf ronnieh at head-cfa.harvard.edu
Fri Nov 22 07:18:10 PST 2002

Hi Gary,

Thanks very much for the detailed explanation. This is a big help.

Thanks again,

> On Thu, 21 Nov 2002, Ronnie Hoogerwerf wrote:
> >
> > > There are a couple of approaches that would work in current and (near)
> > > future versions of OpenMCL:
> > >
> > > a) Copy the contents of the lisp vector of single floats to a C vector
> > > of single floats.  Pass the C vector to foreign code; copy the C vector's
> > > contents back into the lisp vector after the foreign call returns.
> > >
> > > b) Allocate the lisp vector in the C heap; pass the (fixed) address of
> > > its first element to foreign code (which can then side-effect it directly
> > > "Manually" dispose of the lisp vector when you're through with it.
> > >
> >
> > > If you're interested, I'll try to explain (a) and (b) above in greater
> > > detail.
> >
> > Thanks for the reply, I think I have some new ideas to try out now. However
> > I would appreciate it if you could go into some more detail on the suggesti
> > you described above (and maybe give rough example of how to implement this)
> >
> > Thanks again.
> This is the idea behind (a): it stack-allocates a C vector of single
> floats, copies the contents of a lisp vector to that C vector, executes
> an arbitrary body of code (perhaps a foreign function call), then optionally
> copies the (possibly modified) floating-point values from the C vector back
> into the lisp vector.  (That is, it does all of this unless I misspelled
> or misparenthesized something: I don't have an OpenMCL in front of me
> at the moment.)
> (defmacro with-c-single-float-vector ((c-vector lisp-vector &optional
> 					copy-back) &body body)
>   (let* ((nbytes (gensym))
>          (cv (gensym))
>          (lv (gensym)))
>     `(let* ((,lv ,lisp-vector)
>             (,nbytes (* 4 (length ,lv))))
>        (ccl::%stack-block ((,cv ,nbytes))
>          ;; Copy contents of the lisp vector to the C vector:
>          ;;  copy from byte offset 0 to byte offset 0.
>          (ccl::%copy-ivector-to-ptr ,lv 0 ,cv 0 ,nbytes)
>          (let* ((,c-vector ,cv))
>            (multiple-value-prog1   ; overkill, probably
>              (progn , at body)
>              ,@(when copy-back
>               `((ccl::%copy-ptr-to-ivector ,cv 0 ,lv 0 ,nbytes)))))))))
> (b) is a lot simpler, at least syntactically:
> ;;; Allocate a lisp vector of N SINGLE-FLOATs in the foreign heap;
> ;;; return the array and a MACPTR to its 0th element.  The array will
> ;;; never move, but will never get GCed either.
> (defun make-heap-single-float-vector (n)
>   (ccl::%make-heap-ivector arch::subtag-single-float-vector (* 4 n) n))
> When "done" with that vector (assuming that the concept applies),
> dispose of it:
> (ccl::%dispose-heap-ivector v)
> The function CCL::%MAKE-HEAP-IVECTOR could stand to be dressed up some:
> it takes as arguments an "array type code", the vector's size in (8-bit)
> bytes, and the vector's size in elements.  (The size in bytes could obviously
> be computed from the size in elements; the former's required, the latter's
> optional but an error will be signalled if it's not provided.)  I would
> say "hey, don't blame me, I didn't write this" but I have a hunch that
> I may have ...
> Anyhow, baroque as its calling conventions may be, it works; it's used
> by the code that implements many types of streams (so the buffer is
> "nailed down" and can be passed to the OS, but can also be accessed as
> a lisp string or byte vector.)  The good news is that these things aren't
> seen by the GC and so will never move; the bad news is that these things
> aren't seen by the GC and therefore one has to manage their allocation/
> deallocation "manually".

Openmcl-devel mailing list
Openmcl-devel at clozure.com

More information about the Openmcl-devel mailing list