chickadee » jiffi » foreign-safe-lambda**

(foreign-lambda** ...)syntax
(foreign-safe-lambda** ...)syntax

Like foreign-lambda* and foreign-safe-lambda*, except the function body strings can be constructed dynamically at macro expansion time using sprintf. These are building blocks for higher-level macros that generate function bodies based on the macro's arguments.

Usage:

(foreign-lambda**   ; or foreign-safe-lambda**
 RETURN-TYPE
 ((ARG-TYPE ARG_NAME)
  ...)
 BODY-CLAUSE
 ...)

RETURN-TYPE is a foreign type specifier describing the return value.

Each ARG-TYPE is a foreign type specifier describing the argument. Each ARG_NAME is a non-quoted symbol which is used as the variable name within the function body. It must be a valid C variable name.

Each BODY-CLAUSE becomes a separate line of the function body. It can either be a string, or a list of the form (FORMAT-STRING FORMAT-ARG ...), which are arguments passed to sprintf to construct the string.

Because the body string is constructed at macro expansion time, each FORMAT-ARG must be an expression that can be evaluated at macro expansion time in the default environment, such as a quoted symbol, a string, a number, or a call to a built-in procedure.

For obscure technical reasons, you must use C_return(...) instead of the normal return statement to return a value from C.

Examples:

(define return-foo
  (foreign-lambda**
   c-string
   () ; no arguments
   "C_return(\"foo\");"))

(return-foo)   ; ⇒ "foo"

;; Silly example that expands into a foreign-lambda** that performs a
;; simple integer math operation described by the macro caller.
;; X and Y are evaluated at macro-expansion time.
(define-syntax c-math
  (syntax-rules ()
    ((math-fn X OPERATOR Y)
     (foreign-lambda**
      int
      () ; no arguments
      ("C_return(~A ~A ~A);" X 'OPERATOR Y)))))

;; Body becomes "C_return(40 + 2);"
(define return-42 (c-math (* 8 5) + (/ 4 2)))

(return-42)    ; ⇒ 42