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