The two arguments to TRANSLATE-TO-FOREIGN are the Lisp object to be converted, and the name of the foreign type to convert to. First, declare a foreign typedef for :POINTER (since you will ultimately be returning a pointer from the type translator) that you use to hang your type translator on:
(defctype fnv-double :pointer)
Then you can specialize TRANSLATE-TO-FOREIGN on both the Lisp value and the foreign type (using an EQL specializer):
(defmethod translate-to-foreign ((value fnv-double) (name (eql 'fnv-double))) (fnv-foreign-pointer value))
It might be confusing to call both the Lisp and foreign types FNV-DOUBLE, but it is legal because foreign type names are a separate namespace from Lisp types (viva Lisp-N!). It is important to remember the distinction between the two though.
and then declaring something like
(defcfun ("foo" :%foo) :double (x fnv-double))
should just work!
(This is untested and I haven't really been doing any CFFI hacking lately, so I apologize if I missed something obvious here.)
James
I don't quite understand. fnv-double is NOT a pointer. It's a CL struct that holds two arguments, one of which is the foreign pointer. I see I was misusing translate-to-foreign, so maybe I don't need a defctype at all, just an appropriate translate-to-foreign?
rif
rif rif@MIT.EDU writes:
I don't quite understand. fnv-double is NOT a pointer. It's a CL struct that holds two arguments, one of which is the foreign pointer. I see I was misusing translate-to-foreign, so maybe I don't need a defctype at all, just an appropriate translate-to-foreign?
Take the type translators out of the picture for a minute. I assume the C function you want to call looks like:
double foo (double *array);
So, you could define an interface to "foo" like this:
(defcfun "foo" :double (array :pointer))
And call it like:
(let ((fnv ...)) (foo (fnv-foreign-pointer fnv)))
Now, when we want to set up a type translator, we need to introduce a new foreign type that will "own" the translator so that we don't override the default behavior. So instead of the :POINTER argument to FOO above, we define a typedef for :POINTER that we can attach our translation behavior to:
(defctype fnv-pointer :pointer)
;; Define how to convert objects of Lisp type FNV-DOUBLE to foreign ;; type FNV-POINTER. (defmethod translate-to-foreign ((val fnv-double) (name (eql 'fnv-pointer))) (fnv-foreign-pointer val))
(defcfun "foo" :double (array fnv-pointer))
(let ((fnv ...)) (foo fnv)) ;; fnv is automatically converted to a pointer
Hopefully this is more clear about the distinction between FNV-DOUBLE (a Lisp type) and FNV-POINTER (a CFFI foreign type).
James