2017-06-12 32 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)))