[Openmcl-devel] Calling foreign function with float array as argument?
ronnieh at head-cfa.harvard.edu
Fri Nov 22 10:18:10 EST 2002
Thanks very much for the detailed explanation. This is a big help.
> 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