On Sun, Oct 10, 2010 at 5:40 PM, Eric Dobson <endob...@cs.brown.edu> wrote: > I am dealing with a foreign library that has functions that return > error messages in a char** input argument. These need to be explicitly > freed by calling another function. I figured out how to get them into > racket strings by using the _ptr and the _string ctype. But I didn't > see a way to capture the value before conversion to a racket string so > that I could free the original string, and continue to use the _string > conversion process. Is there an easy way to do these two thing > together?
There's a section of the FFI manual (Pointer Functions -> Memory Management) that uses this scenario (or one very similar) as an example: http://docs.racket-lang.org/foreign/foreign_pointer-funcs.html?q=ffi&q=syntax-rules&q=define-syntax#(part._.Memory_.Management) See the definition of the bytes/free ctype -- as well as the discussion about why the code there is subtly incorrect. Or, rather than using a finalizer (and assuming you want a character string as output, not a byte string), you could use bytes->string/[encoding] to produce a character string, then free the original byte string and return the character string. So let's say you have the following, contrived C functions: int fail(); void get_err_msg(int, char**); void free_err_msg(char *); fail() just returns an error code, which you can pass to get_err_msg() to get the corresponding string message. And you're supposed to free the messages by passing them to free_err_msg(). Then, you can create bindings like so: ====================== #lang racket (require ffi/unsafe) ;; create a byte string from a pointer ;; ;; make-byte-string : _pointer -> _bytes (define (make-byte-string ptr) (let loop ((i 0)) (cond ((zero? (ptr-ref ptr _byte i)) (make-sized-byte-string ptr i)) (else (loop (add1 i)))))) ;; A ctype meant to be used as an out param for strings ;; that are allocated by the library ;; ;; _out-string : _ctype (define _out-string (make-ctype _pointer #f (lambda (x) (let* ([b (make-byte-string x)] [s (bytes->string/latin-1 b)]) (free-err-msg x) s)))) (define libtest (ffi-lib "/path/to/shared/lib")) (define fail (get-ffi-obj "fail" libtest (_fun -> _int))) (define get-err-msg (get-ffi-obj "get_err_msg" libtest (_fun _int (s : (_ptr o _out-string)) -> _void -> s))) (define free-err-msg (get-ffi-obj "free_err_msg" libtest (_fun _pointer -> _void))) > > -Eric > _________________________________________________ > For list-related administrative tasks: > http://lists.racket-lang.org/listinfo/users > _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users