使用 Racket 的 FFI 声明函数非常简单,只需使用 _fun
即可和 define-ffi-definer
. (可以在 the PRL blog 上找到教程)例如,我可以为 atoi
进行绑定(bind):
#lang racket
(require ffi/unsafe
ffi/unsafe/define)
(define-ffi-definer define-libc #f)
(define-libc atoi (_fun _string -> _int))
现在我可以用 Racket 字符串调用 atoi
:
> (atoi "5")
5
现在的问题是,我如何调用带有可变元数的 C 函数,例如 printf
,谁的签名是:
int printf(const char *format, ...);
我猜想(因为链接是动态发生的),Racket 代码应该在末尾有一个“rest”参数,它为其余参数采用一个数组(指针),或者以 null 终止或者 (更有可能),由另一个参数表示。但是,我想不出任何好的方法来测试它。
那么,您如何使用 Racket-C FFI 处理可变元数函数?
最佳答案
看看这个解决方案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)))
关于c - Racket/C FFI 中的变量函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44504894/