c - Racket/C FFI 中的变量函数

标签 c racket ffi

使用 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/

相关文章:

c - 数组和链表之间的内存使用

c - 增加 void* 时的垃圾值

rust - 如何仅使用 rustc 而不是 cargo 链接动态 Rust 库?

c++ - 如何通过 C++ FFI 从 Prolog 获取结果到 C++ 变量中

c++ - 在 C 和我的语言之间创建 FFI

c++ - 带符号的 16 位 ALSA PCM 数据到 Linux 上的 U8 转换

string - Racket 语言:如何将字符串转换为变量名

scheme - 编写一个返回字符串中单词出现频率的函数

types - 如何在类型 Racket 中创建 "probability"HOF(或语法)

python - 可以将 Python 与英特尔 Atom Developer SDK (C/C++) 结合使用吗?