[gambit-list] FFI with (char *) buffer

Ben Weaver weaver at coptix.com
Sat Feb 24 16:06:44 EST 2007


Hello Everyone,

I'm creating an FFI that requires writing to and reading from a C
(char *) buffer.  The buffer may contain arbitrary binary data (not
necessarily a character string).  I wrote a few procedures (see below)
to copy the data to and from a u8vector so I can operate on it using
ports.

I'm hoping for comments or suggestions from you all about the code.
Is there a cleaner/better/faster way to do this?  Ideally there would
be some way to open a byte-port directly to the buffer so it wouldn't
have to be copied.  Is this possible?

Thanks in advance,

-Ben



;; Typical use of this code:

(with-input-from-u8vector
 (c-buffer->u8vector foreign-pointer-to-pointer 0 buffer-size )
 (lambda () ...))

(u8vector->c-buffer
 (with-output-to-u8vector
  '(char-encoding: ASCII)
  (lambda () ...))
 foreign-pointer-to-buffer 0 buffer-size)


;; The code

(declare (fixnum) (not safe))

(c-declare #<<eo-declare

typedef const char * const_char_ptr;

eo-declare
)

(c-define-type const-char-buffer "const_char_ptr")
(c-define-type size-type unsigned-int32)
; Using -D_FILE_OFFSET_BITS=64 makes off_t 8 bytes instead of 4
(c-define-type offset-type "off_t" "S64_TO_SCMOBJ" "SCMOBJ_TO_S64" #f)

(define u8vector->c-buffer
  (c-lambda
      (scheme-object (pointer char) offset-type size-type) void
      #<<end-lambda

    off_t i;
    ___U8 c;
    for (i = 0; i < ___arg4; i++) {
           ___SCMOBJ_to_U8(___U8VECTORREF(___arg1, ___FIX(i)), &c, i);
	      ___CAST(char *,___arg2)[i + ___arg3] = c;
    }
end-lambda
))

(define %c-buffer->u8vector
  (c-lambda
      (const-char-buffer scheme-object offset-type size-type)
      void
    #<<end-lambda

    off_t i;
    ___SCMOBJ c;
    ___U8* buff = ___CAST(___U8*, ___arg1);
    for (i = 0; i < ___arg4; i++) {
           ___U8_to_SCMOBJ(buff[i + ___arg3], &c, i);
           ___U8VECTORSET(___arg2, ___FIX(i), c);
    }
    
end-lambda
))

(define (c-buffer->u8vector buff offset size)
  (let ((v (make-u8vector size)))
    (%c-buffer->u8vector buff v offset size)
    v))




More information about the Gambit-list mailing list