简体   繁体   中英

Variable arity functions in Racket/C FFI

Declaring functions with Racket's FFI is simple enough to do with _fun and define-ffi-definer . (A tutorial can be found on the PRL blog ) For example, I can make a binding for atoi :

#lang racket
(require ffi/unsafe
         ffi/unsafe/define)
(define-ffi-definer define-libc #f)
(define-libc atoi (_fun _string -> _int))

And now I can call atoi with Racket strings:

> (atoi "5")
5

The problem now is, how do I call C functions with a variable arity, such as printf , who's signature is:

int printf(const char *format, ...);

I would guess that (since the linking happens dynamically), the Racket code should have a 'rest' argument at the end, which takes an array (pointer) for the rest of the arguments, that is either null terminated or (more likely), indicated by yet another argument. However, I can't think of any good ways to test this.

So, how do you handle variable arity functions with the Racket-C FFI?

Look at this solution c-printf :

(provide c-printf)

(define interfaces (make-hash))

(define (c-printf fmt . args)
  (define itypes
    (cons _string
          (map (lambda (x)
                 (cond [(and (integer? x) (exact? x)) _int]
                       [(and (number? x) (real? x))   _double*]
                       [(string? x)  _string]
                       [(bytes? x)   _bytes]
                       [(symbol? x)  _symbol]
                       [else (error 'c-printf
                                    "don't know how to deal with ~e" x)]))
               args)))
  (let ([printf (hash-ref interfaces itypes
                  (lambda ()
                    ;; Note: throws away the return value of printf
                    (let ([i (get-ffi-obj "printf" #f
                                          (_cprocedure itypes _void))])
                      (hash-set! interfaces itypes i)
                      i)))])
    (apply printf fmt args)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM