ffi: foreign-callable — receive callbacks from C
jolt could call C (foreign-fn -> foreign-procedure) but C could not call back into jolt, which GTK signals (and any callback-taking C API) require. Add the inverse: jolt.ffi/foreign-callable wraps a jolt fn as a C-callable function pointer, mirroring the foreign-fn pipeline. A new jolt.ffi/__ccallable special form carries the fn as a child expression (analyzed + walked by the passes; ir.clj gains an :ffi-callable arm in both child walks) plus literal arg/ret type keywords. The back end lowers it to a locked Chez foreign-callable and returns its entry-point address as a jolt pointer; host/chez/ffi.ss registers the code object so the collector keeps it, and free-callable unlocks it. :collect-safe emits the convention that reactivates the thread on entry, for callbacks fired while it is parked in a :blocking call (a GTK main loop). Test: ffi-binding-test.ss sorts an int array through libc qsort with a jolt comparator (C -> jolt -> C). Re-minted seed.
This commit is contained in:
parent
91eed2b622
commit
c91b6092bc
7 changed files with 178 additions and 70 deletions
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
The memory/library primitives (alloc/free/read/write/sizeof/load-library/
|
||||
ptr->string/string->ptr/null/null?) are provided by the host. foreign-fn lowers
|
||||
a compile-time-typed signature to a real Chez foreign-procedure.")
|
||||
a compile-time-typed signature to a real Chez foreign-procedure. foreign-callable
|
||||
is the inverse — it wraps a jolt fn as a C-callable function pointer so C can
|
||||
call back into jolt (e.g. GTK signal handlers); free-callable releases it.")
|
||||
|
||||
;; foreign-fn binds C symbol `csym` to a typed callable. Expands to the __cfn
|
||||
;; special form (always fully-qualified, so an :as alias on jolt.ffi resolves):
|
||||
|
|
@ -33,3 +35,19 @@
|
|||
(list 'def name (if (= opt :blocking)
|
||||
(list 'jolt.ffi/__cfn csym argtypes rettype :blocking)
|
||||
(list 'jolt.ffi/__cfn csym argtypes rettype))))
|
||||
|
||||
;; foreign-callable wraps a jolt fn `f` as a C-callable function pointer — the
|
||||
;; inverse of foreign-fn, so C can call back INTO jolt (GTK signal handlers, a
|
||||
;; qsort comparator, any C API that takes a callback). Returns the pointer; pass
|
||||
;; it where C expects a function pointer. argtypes/rettype use the same keywords
|
||||
;; as foreign-fn; the args C passes arrive as jolt values and the jolt return is
|
||||
;; marshaled back. The callback stays live until free-callable is called on the
|
||||
;; pointer. Pass a trailing :collect-safe when C invokes the callback from a
|
||||
;; thread parked in a :blocking foreign call (e.g. a GTK main loop):
|
||||
;; (g-signal-connect button "clicked"
|
||||
;; (ffi/foreign-callable on-click [:pointer :pointer] :void :collect-safe)
|
||||
;; (ffi/null))
|
||||
(defmacro foreign-callable [f argtypes rettype & [opt]]
|
||||
(if (= opt :collect-safe)
|
||||
(list 'jolt.ffi/__ccallable f argtypes rettype :collect-safe)
|
||||
(list 'jolt.ffi/__ccallable f argtypes rettype)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue