Chez Scheme 中的 FFI,用于具有可变参数 (varargs) 的 C 函数

Posted

技术标签:

【中文标题】Chez Scheme 中的 FFI,用于具有可变参数 (varargs) 的 C 函数【英文标题】:FFI in Chez Scheme for C functions with variadic arguments (varargs) 【发布时间】:2019-11-16 11:01:12 【问题描述】:

我想使用 foreign-procedure 在 Chez Scheme 中为 C 的 printf 函数编写 FFI。但我不知道我应该把什么作为签名,因为printf 函数中的最后一个参数是一个可变参数。这是我的代码:

(import (chezscheme))

(define (print-format)
    (foreign-procedure "printf" 
        (string void*) int)) ;; <-- Here, the type format is "(arg arg ...) ret"

(print-format "Hello, %s!" "Ryan")

我也试过了,没用:

(define (print-format . args)
    (foreign-procedure "printf" 
        (string args) int))

这也不行:

(define (print-format)
    (foreign-procedure "printf" 
        (string ...) int))

如何在foreign-procedure 的函数签名中指定可变参数?

【问题讨论】:

【参考方案1】:

虽然不是终极解决方案, 您可以使用宏来容纳变量数 系统调用的参数。

create-list 用于为foreign-procedure 提供适当数量的参数 系统调用。

例如宏调用

(print-format "Hello %s and %s" "Ryan" "Greg")

扩展为

((foreign-procedure "printf" (string string string) int) "Hello %s and %s" "Ryan" "Greg")

(define create-list
  (lambda (element n)
    "create a list by replicating element n times"
    (letrec ((helper
           (lambda (lst element n)
             (cond ((zero? n) lst)
                   (else
                    (helper
                     (cons element lst) element (- n 1)))))))
      (helper '() element n))))

(define-syntax print-format
  (lambda (x)
    (syntax-case x ()
      ((_ cmd ...)
       (with-syntax
        ((system-call-spec
          (syntax
           (create-list 'string
                        (length (syntax (cmd ...)))))))
        (with-syntax
         ((proc (syntax
                 (eval
                  `(foreign-procedure "printf"
                                      (,@system-call-spec) int)))))
         (syntax
          (proc cmd ...))))))))

(print-format "Hello %s!" "Ryan")
(print-format "Hello %s and %s" "Ryan" "Greg")

【讨论】:

谢谢。虽然这看起来并不……容易。我很害怕。

以上是关于Chez Scheme 中的 FFI,用于具有可变参数 (varargs) 的 C 函数的主要内容,如果未能解决你的问题,请参考以下文章

Chez Scheme商业级Scheme编译器windows安装包

如何在 Chez-Scheme 中读取一行输入?

Chez Scheme:Macroexpand 实现

如何在 Ubuntu 上安装 Petite Chez Scheme?

在 Linux Mint LMDE 上安装 Chez Scheme 9.4

如何在 chez 方案中加载 slib 库?