2017-06-12 79 views
0

使用球拍的FFI聲明功能足夠簡單,可以使用_fundefine-ffi-definer。 (A教程可以在the PRL blog找到)。例如,我可以爲atoi綁定:Racket/C FFI中的可變組合函數FFI

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

現在我可以打電話atoi與球拍弦:

> (atoi "5") 
5 

現在的問題是,如何我稱C函數具有可變參數數量,如printf,誰的簽名是:

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

我猜想(因爲鏈接^ h動態地出現),Racket代碼在最後應該有一個'rest'參數,它爲剩餘的參數提供一個數組(指針),這個參數可以是null終止或(更可能),由另一個參數表示。但是,我想不出有什麼好的方法來測試它。

那麼,你如何處理Racket-C FFI的可變參數函數呢?

回答

3

看看這個解決方案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)))