Data Model
In addition to the macros and functions provided to build a Clojure API for native libraries, facilities are provided for taking data and loading all the symbols specified by it. This can be useful if a library provides (or an external provider maintains) a data representation of their API, as Clojure data to represent it may be programmatically generated from these sources.
The data to represent an API is a map with the following form:
(def strlen-libspec
{:strlen {:type :function
:symbol "strlen"
:function/args [::mem/c-string]
:function/ret ::mem/long}})
Each key in this map represents a single symbol to be loaded. The value is a map with at least the keys :type
and :symbol
. These are the currently recognized types:
- function
- varargs-factory
- const
- static-var
Each one has its own set of additional keys which can be added to the map. Both function
and varargs-factory
have the three keys :function/args
, :function/ret
, and :function/raw-fn?
. The const
type has :const/type
and static-var
has :static-var/type
.
This data can be passed to the function reify-libspec
, which will take the data and return a map from the same keys as the input map to whatever value is appropriate for a given symbol type (e.g. a Clojure function for function
, a value for const
, etc.).
(ffi/reify-libspec strlen-libspec)
;; => {:strlen #function[...]}
This functionality can be extended by specifying new types as implementations of the multimethod reify-symbolspec
, although it’s recommended that for any library authors who do so, namespaced keywords be used to name types.