From: David Steuber
Subject: Please help me make this better
Date: 
Message-ID: <87fyzs8cl1.fsf@david-steuber.com>
I started by trying to wrap uffi:with-foreign-object, but that didn't
work out (although for my example case below I'm sure I can do that).
What I have is a macro that takes a lisp vector and uses it to create
and initialize a foreign vector.

(defmacro with-opengl-vector ((var vec) &rest body)
  "Allocate foreign vector var and copy vec into it.  Free var after
executing body and return value of body."
  (let ((lvec (gensym))
        (tvec (gensym)))
  `(let* ((,lvec ,vec)
          (,tvec (get-vec-type ,lvec))
          (,var  (allocate-opengl-vec ,tvec (length ,lvec))))
     (unwind-protect
          (progn
            (init-opengl-vec ,var ,tvec ,lvec)
            ,@body)
       (uffi:free-foreign-object ,var)))))

(defun get-vec-type (vec)
  (let ((type (type-of (aref vec 0))))
    (cond ((eq type 'single-float) :float)
          ((eq type 'double-float) :double)
          ((eq type 'bit) :int)
          ((and (listp type) (eq (car type) 'integer)) :int)
          (t (error "Unandled type ~S in GLM::GET-VEC-TYPE" type)))))

(defun allocate-opengl-vec (type size)
  (ecase type
    (:float  (uffi:allocate-foreign-object :float size))
    (:double (uffi:allocate-foreign-object :double size))
    (:int    (uffi:allocate-foreign-object :int size))))

(defun init-opengl-vec (fv type v)
  (ecase type
    (:float  (dotimes (i (length v))
               (setf (uffi:deref-array fv :float i)
                     (aref v i))))
    (:double (dotimes (i (length v))
               (setf (uffi:deref-array fv :double i)
                     (aref v i))))
    (:int    (dotimes (i (length v))
               (setf (uffi:deref-array fv :int i)
                     (aref v i))))))

An example of use:

    (glm:with-opengl-vector (position #(7.0 7.0 12.0 0.0))
      (gl:lightfv gl:+light0+ gl:+position+ position))

In this case, I have a constant vector, so everything can be known by
the macro.  In the general case, I expect to use a variable or
function return value to hold the vector.

I also wonder if my use of TYPE-OF is risk free.  Maybe I should be
using TYPEP instead.

-- 
An ideal world is left as an excercise to the reader.
   --- Paul Graham, On Lisp 8.1