简体   繁体   English

Racket / C FFI中的可变arity函数

[英]Variable arity functions in Racket/C FFI

Declaring functions with Racket's FFI is simple enough to do with _fun and define-ffi-definer . 使用Racket的FFI声明函数非常简单,只需使用_fundefine-ffi-definer _fun (A tutorial can be found on the PRL blog ) For example, I can make a binding for atoi : (可以在PRL博客上找到教程)例如,我可以为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了:

> (atoi "5")
5

The problem now is, how do I call C functions with a variable arity, such as printf , who's signature is: 现在的问题是,如何使用变量arity调用C函数,例如printf ,其签名是:

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. 我猜(由于链接是动态发生的),Racket代码的末尾应该有一个“ rest”参数,该参数为其余参数采用一个数组(指针),即为null终止或(更有可能) ,由另一个论点表示。 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? 那么,如何使用Racket-C FFI处理可变arity函数?

Look at this solution c-printf : 看一下这个解决方案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)))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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