Update of /project/cl-gsl/cvsroot/cl-gsl In directory common-lisp.net:/tmp/cvs-serv29878
Modified Files: ffi.lisp Log Message: Added macros which allocate, bind, and free foreign structures.
Date: Mon Apr 4 02:44:15 2005 Author: edenny
Index: cl-gsl/ffi.lisp diff -u cl-gsl/ffi.lisp:1.3 cl-gsl/ffi.lisp:1.4 --- cl-gsl/ffi.lisp:1.3 Tue Mar 15 04:15:20 2005 +++ cl-gsl/ffi.lisp Mon Apr 4 02:44:15 2005 @@ -56,7 +56,8 @@
;; ----------------------------------------------------------------------
-;; TODO: size_t may not always be unsigned long, could also be unsigned int. +;; TODO: size_t may not always be unsigned long, could also be unsigned int +;; on some systems? (define-foreign-type size-t :unsigned-long)
(def-foreign-struct gsl-complex @@ -192,56 +193,76 @@ ;; typedef long double * gsl_complex_packed_array_long_double ; ;; typedef long double * gsl_complex_packed_long_double_ptr ;
-;; typedef struct -;; { -;; long double dat[2]; -;; } -;; gsl_complex_long_double; - ;; ----------------------------------------------------------------------
(defun gsl-complex->complex (z-ptr) - ;; TODO: this seems to work with pointers and values -;; (declare (gsl-complex-def z)) + "Copies the value of the foreign object pointed to by Z-PTR to a lisp object +of type (complex (double-float)). Returns the lisp object." (let ((dat-array (uffi:get-slot-value z-ptr '(:array :double) 'cl-gsl::dat))) (complex (uffi:deref-array dat-array :double 0) (uffi:deref-array dat-array :double 1))))
(defun gsl-complex-float->complex (z-ptr) + "Copies the value of the foreign object pointed to by Z-PTR to a lisp object +of type (complex (single-float)). Returns the lisp object." (let ((dat-array (uffi:get-slot-value z-ptr '(:array :float) 'cl-gsl::dat))) (complex (uffi:deref-array dat-array :float 0) (uffi:deref-array dat-array :float 1))))
-;; FIXME: this returns a pointer to a gsl-complex. Is this correct? -;; How do we free it? -;; Replace with a with-complex->gsl-complex macro that cleans up after -;; itself -(defun complex->gsl-complex-ptr (z) - (let* ((z-ptr (uffi:allocate-foreign-object 'gsl-complex)) - (dat-array (uffi:get-slot-value z-ptr '(:array :double) 'cl-gsl::dat))) - (setf (uffi:deref-array dat-array :double 0) (realpart z)) - (setf (uffi:deref-array dat-array :double 1) (imagpart z)) - z-ptr)) - -;; FIXME: see above -(defun complex->gsl-complex-float-ptr (z) - (let* ((z-ptr (uffi:allocate-foreign-object 'gsl-complex-float)) - (dat-array (uffi:get-slot-value z-ptr '(:array :float) 'cl-gsl::dat))) - (setf (uffi:deref-array dat-array :float 0) (realpart z)) - (setf (uffi:deref-array dat-array :float 1) (imagpart z)) - z-ptr)) - - -;; TODO: generalize to all supported types? -(defun lisp-vec->c-array (v) - (declare (vector v)) - (let* ((len (length v)) - (c-ptr (uffi:allocate-foreign-object :double len))) - (dotimes (i len) - (setf (uffi:deref-array c-ptr :double i) (aref v i))) - c-ptr))
-;; TODO: generalize to all supported types? +(defmacro with-complex-double-float->gsl-complex-ptr ((c-ptr complex-val) + &body body) + "Copies the value of COMPLEX-VALUE, of type (complex (double-float)), +to a newly created foreign object of type gsl_complex. C-PTR is a pointer +to the foreign object. Returns the values of BODY and frees the memory +allocated for the foreign object." + (let ((array (gensym))) + `(let* ((,c-ptr (uffi:allocate-foreign-object 'gsl-complex)) + (,array (uffi:get-slot-value ,c-ptr + '(:array :double) + 'cl-gsl::dat))) + (unwind-protect + (progn + (setf (uffi:deref-array ,array :double 0) (realpart ,complex-val)) + (setf (uffi:deref-array ,array :double 1) (imagpart ,complex-val)) + ,@body) + (uffi:free-foreign-object ,c-ptr))))) + + +(defmacro with-complex-single-float->gsl-complex-float-ptr ((c-ptr complex-val) + &body body) + "Copies the value of COMPLEX-VALUE, of type (complex (single-float)), +to a newly created foreign object of type gsl_complex_float. C-PTR is a pointer +to the foreign object. Returns the values of BODY and frees the memory +allocated for the foreign object." + (let ((array (gensym))) + `(let* ((,c-ptr (uffi:allocate-foreign-object 'gsl-complex-float)) + (,array (uffi:get-slot-value ,c-ptr + '(:array :float) + 'cl-gsl::dat))) + (unwind-protect + (progn + (setf (uffi:deref-array ,array :float 0) (realpart ,complex-val)) + (setf (uffi:deref-array ,array :float 1) (imagpart ,complex-val)) + ,@body) + (uffi:free-foreign-object ,c-ptr))))) + + +(defmacro with-lisp-vec->c-array ((c-ptr lisp-vec) &body body) + (let ((len (gensym)) + (i (gensym))) + `(progn + (let* ((,len (length ,lisp-vec)) + (,c-ptr (uffi:allocate-foreign-object :double ,len))) + (unwind-protect + (progn + (dotimes (,i ,len) + (setf (uffi:deref-array ,c-ptr :double ,i) + (aref ,lisp-vec ,i))) + ,@body) + (uffi:free-foreign-object ,c-ptr)))))) + + (defun c-array->lisp-vec (c-ptr len) (let ((lisp-vec (make-array len :element-type 'double-float))) (dotimes (i len) @@ -249,6 +270,9 @@ lisp-vec))
(defun complex-packed-array->lisp-vec (z-ptr len) + "Copies the complex values of a foreign array to a lisp array. Z-PTR is +a pointer the the foreign array of length LEN. Returns a lisp array of +complex elements, also of length LEN." (declare (gsl-complex-packed-def z-ptr)) (let ((lisp-vec (make-array (/ len 2) :element-type 'complex))) (dotimes (i (/ len 2))