From: Hoehle, Joerg-C. <Joe...@t-...> - 2005-12-20 16:43:29
|
Surendra Singhi asks: >(ffi:def-call-out return_string > (:name "return_string") > (:arguments (len (ffi:c-ptr ffi:uint) :out)) > (:return-type (FFI:C-POINTER character) :malloc-free) > (:library "test.dll") > (:language :stdc)) >And my objective is to get a string in lisp which might >contain the null symbol. This is no different from any other case with variable length arrays, shown in this list several times already. >(let (ptr len str) > (multiple-value-setq (ptr len) (return_string)) > (setf str (ffi:with-c-var (array 'ffi:c-pointer ptr) > (ffi:cast array `(ffi:c-ptr (ffi:c-array >character ,len))))) > str) >Is the above the best way to do it, and is it correct? Can I do it more >efficiently and in a better way? It's not that bad, but with-c-var is superfluous. Since you use :return-type (ffi-cpointer character), just use (with-c-place (v ptr) (offset v 0 `(c-array character ,len))) Or use a plain c-pointer :return-type, together with (foreign-value (foreign-variable ptr (parse-c-type '(c-array character ,len))) Do as you please. Another solution might be to use WITH-FOREIGN-STRING to pass the buffer to the foreign string, then read it back using the above technique. But in your case, you received the pointer from the function and did not pass it some buffer. You may wonder about with-c-var (bad)/with-c-place(good). One creates a closure and uses a trampoline technique to achieve the results, whereas the other is nothing but symbol macro substitution, no closure, just the call to OFFSET and PARSE-C-TYPE (which gets optimized away). I think it makes quite a difference, despite the similar names. Do you think that impnotes should mention such gory details? If yes, would you be willing to provide text snippets as to what you'd consider a valuable addition? Regards, Jorg Hohle. |