I want to write a FFI for printf
function of C in Chez Scheme using foreign-procedure
. But I cannot figure out what I should put as the signature, since the last argument in printf
function is a variadic argument. Here's my code:
(import (chezscheme))
(define (print-format)
(foreign-procedure "printf"
(string void*) int)) ;; <-- Here, the type format is "(arg arg ...) ret"
(print-format "Hello, %s!" "Ryan")
I have tried this as well to no avail:
(define (print-format . args)
(foreign-procedure "printf"
(string args) int))
This is not working either:
(define (print-format)
(foreign-procedure "printf"
(string ...) int))
How do you specify variadic arguments in function signature for foreign-procedure
?
Although it is not the ultimate solution, you could use macros to accommodate variable number of parameters to a system call.
create-list
is used to supply proper number of parameters to the foreign-procedure
system call.
For example, macro call
(print-format "Hello %s and %s" "Ryan" "Greg")
is expanded as
((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")