From a75c1a9c0e1bd096ce1bf1887140f6d0e5e4cd9d Mon Sep 17 00:00:00 2001 From: Joshua Suskalo Date: Sat, 25 Sep 2021 10:36:43 -0500 Subject: [PATCH] Fill in section on complex wrappers --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c354579..055215e 100644 --- a/README.md +++ b/README.md @@ -202,7 +202,39 @@ value is being mutated on another thread. A parallel function `fswap!` is also provided, but it does not provide any atomic semantics either. -### TODO Complex Wrappers +### Complex Wrappers +Some functions require more complex code to map nicely to a Clojure function. +The `defcfn` macro provides facilities to wrap the native function with some +Clojure code to make this easier. + +```clojure +(defcfn takes-array + "takes_array_with_count" [::ffi/pointer ::ffi/long] ::ffi/void + native-fn + [ints] + (let [arr-len (count ints) + int-array (serialize ints [::ffi/array ::ffi/int arr-len] + (native-fn (ffi/address-of int-array) arr-len))])) +``` + +The symbol `native-fn` can be any unqualified symbol, and names the native +function being wrapped. It must be called in the function body below if you want +to call the native code. + +This `serialize` function has a paired `deserialize`, and allows marshaling +Clojure data back and forth to native data structures. + +This can be used to implement out variables often seen in native code. + +```clojure +(defcfn out-int + "out_int" [::ffi/pointer] ::ffi/void + native-fn + [i] + (let [int-ptr (serialize i [::ffi/pointer ::ffi/int])] + (native-fn int-ptr) + (deserialize int-ptr [::ffi/pointer ::ffi/int]))) +``` ### TODO Scopes