chickadee » jiffi » define-binding**

(define-binding** ...)syntax

Like define-binding, except that it is based on foreign-lambda**, so you can specify a custom body of C code, or construct the function body at macro expansion time.


(define-binding** SCHEME-NAME
  safe:   SAFE                          ; optional
  return: RETURN-TYPE                   ; optional
  args:   ((ARG-TYPE ARG_NAME) ...)     ; optional

SCHEME-NAME is the procedure name to define in Scheme.

If SAFE is #t, the binding will use foreign-safe-lambda**. You should do this if you want the C function to be able to call back into Scheme. If SAFE is #f or the safe: clause is omitted, the binding will use foreign-lambda**.

If the return: clause is omitted, the return type is void. If the args: clause is omitted, the function accepts no arguments.

Each ARG_NAME must be a non-quoted symbol that is a valid C variable name. You can then use ARG_NAME within the function body.

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. See foreign-lambda** for more information.

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


;; Create a binding to arbitrary C code.
(define-binding** squaref
  return: float
  args: ((float x))
  "C_return(x * x);")

(squaref 8.0)  ; ⇒ 64.0

;; Expands into a define-binding** that gets the value of a struct
;; field. This is similar to how struct-getter is implemented.
(define-syntax define-struct-getter
  (syntax-rules ()
    ((define-struct-getter GETTER
     (define-binding** GETTER
       return: FIELD-TYPE
       args: (((c-pointer STRUCT_NAME) obj))
       ;; These could easily be one line, but they are split to
       ;; demonstrate that you can have multiple body clauses:
       ("obj->~A" 'FIELD-NAME)

(define-struct-getter event-type
  "FOO_Event" "type" int)

;; Expands to:
;;   (define-binding** event-type
;;     return: int
;;     args: (((c-pointer "FOO_Event") obj))
;;     "C_return("
;;     ("obj->~A" '"type")
;;     ");"))));;
;; Which produces the C function body:
;;   C_return(
;;   obj->type
;;   );