Thread view

Joerg,
I have a c-pointer OBJ pointing to an area of size (N+1)*sizeof(ulong).
and 2 lisp objects: an int INCR and a VEC (vector N ulong).
I want to copy the VEC onto the the tail of OBJ and increment the first ulong
on OBJ by INCR.
Using a foreign variable temp, I can do that like this:
(setf temp obj)
(incf (cast temp 'ulong) incr)
(setf (deref (cast temp `(c-ptr (c-array ulong ,(length vec))))) vec)
I don't want to use the external variable temp.
What is the best way to do that?
(with-c-var (v 'ulong obj)
(incf (cast fvar 'ulong) incr))
(with-c-var (v `(c-ptr (c-array ulong ,(length vec))) obj)
(setf (deref fvar) vec))
thanks!
Sam

[It appears the message did not make it through to the list back in May
and nobody ever received it.]
Hi,
[Replying to clisp-list since that's where Sam's query went as well.]
Sam Steingold wrote:
> I have a c-pointer OBJ pointing to an area of size (N+1)*sizeof(ulong).
> and 2 lisp objects: an int INCR and a VEC (vector N ulong).
> I want to copy the VEC onto the the tail of OBJ
Do you mean positions 1..N, skipping position 0?
> and increment the first ulong on OBJ by INCR.
> Using a foreign variable temp, I can do that like this:
> (setf temp obj)
> (incf (cast temp 'ulong) incr)
> (setf (deref (cast temp `(c-ptr (c-array ulong ,(length vec))))) vec)
Are you sure this is correct? Perhaps I'm getting old and confused but
it looks inconsistent. Why deref a c-ptr? Why not use the c-array as is?
Esp. since you do the incr without such deref.
> I don't want to use the external variable temp.
There's nothing wrong with an aux variable except it's not reentrant
-- and completely superfluous :-)
> (with-c-var (v 'ulong obj)
> (incf (cast v 'ulong) incr))
> (with-c-var (v `(c-ptr (c-array ulong ,(length vec))) obj)
> (setf (deref v) vec))
How does that write to the tail and ignore the first position?
> What is the best way to do that?
I think this might be a good use-case for FFI:MEMORY-AS and esp. its
optional offset parameter.
(incf (memory-as OBJ (parse-c-type 'ulong)) INCR)
(setf (memory-as OBJ (parse-c-type `(c-array ulong ,(length VEC)))
(sizeof 'ulong)) VEC)
and verify that the compiler-macro on parse-c-type does it job.
Please check whether you need to DEREF obj first. Is it really a
pointer or does it represent the memory block itself?
Things are simpler (and preferable) in the latter case.
Generally, if a foreign place (or variable) represents an array,
there's no need for an extra C-POINTER indirection.
>also, is there a better way to write these:
(defmacro extract0 ((var x) &body body)
(let ((fvar (gensym "EXTRACT0")))
`(with-c-var (,fvar 'c-pointer ,x)
(symbol-macrolet ((,var (deref (cast ,fvar '(c-ptr ulong)))))
,@body))))
(defmacro extract1 ((var x) &body body)
(let ((fvar (gensym "EXTRACT1")))
`(with-c-var (,fvar 'c-pointer ,x)
(symbol-macrolet
((,var (element (deref (cast ,fvar '(c-ptr (c-array ulong 2)))) 1)))
,@body))))
You should use FFI:OFFSET for sliding windows instead of CAST.
(offset obj (sizeof 'ulong) `(c-array ulong ,(length vec)))
Your usage of (,fvar 'c-pointer) seems strange to me: basically
you're wasting a c-pointer and immediately deref it. Why not work
with the object directly (or at least its FOREIGN-ADDRESS)?
Wouldn't
(defmacro extract# ((var x) &body body)
`(with-c-var (,var (offset ,x # 'ulong)) ,@body))
work as well?
What do you want to achieve? Is it important to bind var to a FFI PLACE?
(such that you can use SETF?)
Doesn't symbol-macrolet (or with-c-var) hide the true cost of accessing this stuff?
Regards,
Jörg Höhle