Hello,
I'm using cffi, and I need to perform the common task of passing Lisp arrays to foreign code.
This task comes up a lot in scientific code, matrix math, image processing, etc.
Normally, it involves a lot of boilerplate to allocate a pointer, copy data Lisp to foreign
memory, copy the data back, and deallocate the memory. Getting the copying to run
fast can be tricky.
Hence I wrote a package to automate it. It maintains a set of specialized copying
functions to copy from array of Lisp type X to foreign memory of type Y. On SBCL, copying
doesn't cons and is reasonably fast (~200 MB a second, there and back)
I've put the package here:
http://www.megaupload.com/?d=CX1XFMU6
Sorry for the megaupload, and its imposed delay, but I didn't want to spam the list with a 100K file.
The package includes a MANUAL.txt and a test package.
I'd be happy to have this included in a user contrib section of CFFI, if the maintainers
think it would be useful.
Here's an example the main macro does:
(LET ((U (MAKE-ARRAY 100 :ELEMENT-TYPE 'SINGLE-FLOAT :INITIAL-ELEMENT 1.0)))
;;
(WITH-ARRAY-AS-FOREIGN-POINTER
(U PU :FLOAT ;; LISP-VAR POINTER-VAR CFFI-FOREIGN-TYPE
:LISP-TYPE SINGLE-FLOAT ;; promise U is a single-float array
:START 2 ;; begin at index 2 of of Lisp array
:END 7 ;; last index used is 6
:COPY-TO-FOREIGN T ;; put contents of Lisp into foreign memory
:COPY-FROM-FOREIGN T) ;; copy back from FFI space to lisp array
;;
;; at this point, PU is a foreign pointer containing data copied
;; from the array starting at element 1 and ending at 6, of type :FLOAT.
(SOME-FOREIGN-FUNCTION PU))
;;
;; at end, all foreign memory is deallocated, and U has been copied
;; back from foreign space, but the 0th element of U is untouched
;; because START was 1, not 0
)
-John
Here's a patch that makes name translation between lisp and foreign names more flexible. I often find that I'm using libraries that don't use underscore_separated_names, and rather than always doing
(defcfun (some-fun "someFun") ...)
I end up doing local hacks so I can just define the translation rules once and only use the (symbol "string") style for exceptions.
This patch makes those local hacks less hacky. It means in my wrapper, I can define methods on CFFI:LISP-NAME and CFFI:FOREIGN-NAME (as in http://github.com/sellout/CL-LLVM/blob/master/cffi.lisp) to create custom translations (specialized on the package, so other wrappers can use their own translations).
Those don't fail, but:
UFFI-TESTS> (let ((native-string "test string"))
(uffi:with-foreign-string (fs native-string)
(ensure-char-character
(deref-pointer fs :char))))
#\t
UFFI-TESTS> (let ((native-string "test string"))
(uffi:with-foreign-string (fs native-string)
(deref-pointer fs :char)))
116
The latter would return #\t in uffi-compat.
Em 22 de agosto de 2010 18:25, Luís Oliveira <luismbo(a)gmail.com> escreveu:
2010/8/10 Gustavo <gugamilare(a)gmail.com>:
> > I found one inconsistency in uffi's documentation. Uffi's doc says that
> > dereferencing types :char and :unsigned-char return characters where
> > actually it returns integers (at least here).
>
> Does that mean these tests fail for you?
> <http://git.b9.com/?p=uffi.git;a=blob;f=tests/objects.lisp>
>
> --
> Luís Oliveira
> http://r42.eu/~luis/ <http://r42.eu/%7Eluis/>
>